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

Linux Kernel Patch v2.2, patch-2.2.6 (00/34)

8 views
Skip to first unread message

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part00

lines added deleted
linux/Documentation/Changes : 32 19 0
linux/Documentation/Configure.help : 78 39 5
linux/Documentation/fb/vesafb.txt : 88 55 17
linux/Documentation/filesystems/00-INDEX : 8 2 0
linux/Documentation/filesystems/ufs.txt : 49 49 0
linux/Documentation/sound/PCM1-pro : 17 17 0
linux/Documentation/sound/mwave : 16 2 8
linux/Documentation/sysctl/README : 34 4 6
linux/Documentation/sysctl/fs.txt : 37 13 3
linux/Documentation/sysctl/kernel.txt : 63 23 3
linux/Documentation/sysctl/sunrpc.txt : 20 20 0
linux/Documentation/sysctl/vm.txt : 198 40 107
linux/MAINTAINERS : 22 8 1
linux/Makefile : 36 6 4
linux/arch/alpha/lib/io.c : 45 6 5
linux/arch/i386/defconfig : 15 3 1
linux/arch/i386/kernel/io_apic.c : 147 43 28
linux/arch/i386/kernel/irq.c : 20 2 5
linux/arch/i386/kernel/irq.h : 7 1 0
linux/arch/i386/kernel/mca.c : 979 264 257
linux/arch/i386/kernel/smp.c : 15 4 2
linux/arch/ppc/8xx_io/enet.c : 7 1 0
linux/arch/ppc/boot/head.S : 4 0 1
linux/arch/ppc/lib/string.S : 7 0 1
linux/arch/ppc/mbxboot/head.S : 4 0 1
linux/drivers/block/Makefile : 10 4 0
linux/drivers/block/genhd.c : 51 14 6
linux/drivers/block/ide-cd.c : 9 0 3
linux/drivers/cdrom/Config.in : 10 4 0
linux/drivers/cdrom/mcd.c : 26 4 2
linux/drivers/cdrom/mcd.h : 29 0 19
linux/drivers/cdrom/sjcd.c : 35 10 1
linux/drivers/char/Config.in : 7 1 0
linux/drivers/char/Makefile : 22 9 0
linux/drivers/char/bttv.c : 30 9 1
linux/drivers/char/bttv.h : 7 1 0
linux/drivers/char/cyclades.c : 228 58 24
linux/drivers/char/dtlk.c : 8 0 2
linux/drivers/char/isicom.c : 15 2 0
linux/drivers/char/istallion.c : 7 1 0
linux/drivers/char/mem.c : 66 35 8
linux/drivers/char/radio-aimslab.c : 7 1 0
linux/drivers/char/radio-aztech.c : 7 1 0
linux/drivers/char/radio-cadet.c : 403 403 0
linux/drivers/char/radio-gemtek.c : 7 1 0
linux/drivers/char/radio-miropcm20.c : 7 1 0
linux/drivers/char/radio-rtrack2.c : 7 1 0
linux/drivers/char/radio-sf16fmi.c : 7 1 0
linux/drivers/char/radio-typhoon.c : 9 2 1
linux/drivers/char/radio-zoltrix.c : 15 1 4
linux/drivers/char/softdog.c : 14 3 5
linux/drivers/char/stallion.c : 7 1 0
linux/drivers/char/videodev.c : 32 12 0
linux/drivers/macintosh/adb.c : 7 0 1
linux/drivers/net/Makefile : 8 1 1
linux/drivers/net/defxx.c : 82 18 6
linux/drivers/net/defxx.h : 10 4 0
linux/drivers/net/irda/Makefile : 8 1 1
linux/drivers/net/irda/irport.c : 370 129 105
linux/drivers/net/irda/irtty.c : 136 26 21
linux/drivers/net/irda/pc87108.c : 149 27 31
linux/drivers/net/irda/tekram.c : 8 1 1
linux/drivers/net/irda/uircc.c : 999 283 247
linux/drivers/net/irda/w83977af_ir.c : 607 121 124
linux/drivers/net/rclanmtl.c : 28 6 2
linux/drivers/net/rclanmtl.h : 8 1 1
linux/drivers/net/rcpci45.c : 540 181 145
linux/drivers/net/syncppp.c : 16 2 1
linux/drivers/net/tlan.c : 7 1 0
linux/drivers/net/z85230.c : 123 27 9
linux/drivers/pci/oldproc.c : 14 6 2
linux/drivers/sbus/audio/dmy.c : 7 0 1
linux/drivers/scsi/ChangeLog.ncr53c8xx : 15 12 0
linux/drivers/scsi/ChangeLog.sym53c8xx : 219 219 0
linux/drivers/scsi/Config.in : 27 8 1
linux/drivers/scsi/Makefile : 14 8 0
linux/drivers/scsi/NCR5380.c : 81 9 11
linux/drivers/scsi/README.ncr53c8xx : 187 95 41
linux/drivers/scsi/aha152x.c : 118 58 22
linux/drivers/scsi/gdth.c : 867 301 149
linux/drivers/scsi/gdth.h : 381 253 30
linux/drivers/scsi/gdth_proc.c : 738 538 68
linux/drivers/scsi/gdth_proc.h : 16 2 1
linux/drivers/scsi/hosts.c : 20 7 0
linux/drivers/scsi/megaraid.c : 16 1 2
linux/drivers/scsi/megaraid.h : 9 0 3
linux/drivers/scsi/ncr53c8xx.c : 150 41 7
linux/drivers/scsi/ncr53c8xx.h : 1118 8 1075
linux/drivers/scsi/pci2000.c : 440 181 88
linux/drivers/scsi/pci2000.h : 115 53 21
linux/drivers/scsi/pci2220i.c : 1154 462 243
linux/drivers/scsi/pci2220i.h : 119 57 22
linux/drivers/scsi/psi240i.c : 26 3 3
linux/drivers/scsi/psi_dale.h : 43 14 20
linux/drivers/scsi/psi_roy.h : 43 14 20
linux/drivers/scsi/qlogicfc.c : 310 51 67
linux/drivers/scsi/qlogicfc_asm.c : 6159 3176 2869
linux/drivers/scsi/sg.c : 2134 1440 543
linux/drivers/scsi/sym53c8xx.c : 11768 11768 0
linux/drivers/scsi/sym53c8xx.h : 116 116 0
linux/drivers/scsi/sym53c8xx_defs.h : 1195 1195 0
linux/drivers/scsi/wd33c93.c : 8 2 0
linux/drivers/sound/ad1848.c : 41 18 3
linux/drivers/sound/audio.c : 20 5 2
linux/drivers/sound/dev_table.c : 7 1 0
linux/drivers/sound/dev_table.h : 7 1 0
linux/drivers/sound/dmabuf.c : 66 6 5
linux/drivers/sound/es1370.c : 99 29 9
linux/drivers/sound/es1371.c : 98 29 8
linux/drivers/sound/sb.h : 7 1 0
linux/drivers/sound/sb_card.c : 8 3 0
linux/drivers/sound/sb_common.c : 81 19 5
linux/drivers/sound/sb_mixer.c : 7 1 0
linux/drivers/sound/sonicvibes.c : 153 58 12
linux/drivers/sound/sscape.c : 10 3 1
linux/drivers/video/promcon.c : 7 1 0
linux/drivers/video/sgivwfb.c : 7 1 0
linux/drivers/video/vesafb.c : 26 5 1
linux/fs/affs/namei.c : 49 1 21
linux/fs/coda/dir.c : 126 2 47
linux/fs/ext2/namei.c : 198 7 86
linux/fs/ext2/super.c : 8 0 2
linux/fs/fat/inode.c : 29 14 2
linux/fs/hfs/dir.c : 8 0 2
linux/fs/inode.c : 24 1 10
linux/fs/minix/inode.c : 10 2 2
linux/fs/minix/namei.c : 72 1 42
linux/fs/msdos/namei.c : 463 69 258
linux/fs/namei.c : 157 87 21
linux/fs/ncpfs/dir.c : 18 4 1
linux/fs/ncpfs/inode.c : 8 2 0
linux/fs/nfs/dir.c : 179 16 56
linux/fs/nfs/inode.c : 8 2 0
linux/fs/nfs/symlink.c : 16 3 4
linux/fs/nfsd/nfs3proc.c : 19 4 1
linux/fs/nfsd/nfsproc.c : 19 4 1
linux/fs/nfsd/vfs.c : 8 1 1
linux/fs/ntfs/Makefile : 8 1 1
linux/fs/ntfs/attr.c : 314 100 36
linux/fs/ntfs/attr.h : 7 4 0
linux/fs/ntfs/dir.c : 153 32 13
linux/fs/ntfs/dir.h : 4 1 0
linux/fs/ntfs/fs.c : 53 8 4
linux/fs/ntfs/inode.c : 286 72 27
linux/fs/ntfs/inode.h : 5 2 0
linux/fs/ntfs/ntfsendian.h : 45 9 8
linux/fs/ntfs/ntfstypes.h : 25 6 2
linux/fs/ntfs/super.c : 103 27 9
linux/fs/ntfs/super.h : 8 1 1
linux/fs/ntfs/support.c : 10 4 0
linux/fs/open.c : 28 10 1
linux/fs/proc/link.c : 8 1 1
linux/fs/smbfs/dir.c : 63 1 15
linux/fs/super.c : 7 1 0
linux/fs/sysv/namei.c : 69 2 41
linux/fs/ufs/namei.c : 204 7 92
linux/fs/ufs/super.c : 158 35 24
linux/fs/ufs/util.h : 114 62 28
linux/fs/umsdos/dir.c : 57 29 8
linux/fs/umsdos/emd.c : 12 0 4
linux/fs/umsdos/inode.c : 53 3 10
linux/fs/umsdos/namei.c : 363 37 187
linux/fs/vfat/namei.c : 64 4 24
linux/include/asm-alpha/io.h : 8 1 1
linux/include/asm-alpha/semaphore-helper.h : 8 1 1
linux/include/asm-alpha/semaphore.h : 67 25 21
linux/include/asm-alpha/uaccess.h : 172 82 68
linux/include/asm-i386/pgtable.h : 8 1 1
linux/include/linux/cyclades.h : 86 29 5
linux/include/linux/ext2_fs_sb.h : 8 0 2
linux/include/linux/fs.h : 22 9 0
linux/include/linux/mca.h : 65 15 15
linux/include/linux/pagemap.h : 8 1 1
linux/include/linux/pci.h : 10 4 0
linux/include/linux/proc_fs.h : 7 1 0
linux/include/linux/socket.h : 7 1 0
linux/include/linux/ufs_fs.h : 89 27 10
linux/include/linux/ufs_fs_sb.h : 71 23 10
linux/include/linux/umsdos_fs.p : 7 1 0
linux/include/net/irda/discovery.h : 65 65 0
linux/include/net/irda/ircomm_common.h : 184 67 41
linux/include/net/irda/irda.h : 252 145 68
linux/include/net/irda/irda_device.h : 113 24 30
linux/include/net/irda/iriap.h : 36 6 10
linux/include/net/irda/irkbd.h : 91 91 0
linux/include/net/irda/irlan_client.h : 17 2 2
linux/include/net/irda/irlan_common.h : 26 4 2
linux/include/net/irda/irlan_eth.h : 19 3 3
linux/include/net/irda/irlan_provider.h : 18 3 2
linux/include/net/irda/irlap.h : 49 8 12
linux/include/net/irda/irlap_event.h : 35 5 3
linux/include/net/irda/irlap_frame.h : 147 39 51
linux/include/net/irda/irlmp.h : 212 55 59
linux/include/net/irda/irlmp_event.h : 17 2 2
linux/include/net/irda/irlmp_frame.h : 65 21 21
linux/include/net/irda/irmod.h : 212 12 162
linux/include/net/irda/irobex.h : 18 4 1
linux/include/net/irda/irqueue.h : 28 6 2
linux/include/net/irda/irttp.h : 90 19 23
linux/include/net/irda/irvtd.h : 94 14 26
linux/include/net/irda/irvtd_driver.h : 122 0 122
linux/include/net/irda/timer.h : 82 21 19
linux/include/net/irda/uircc.h : 28 4 2
linux/include/net/sock.h : 20 7 0
linux/include/scsi/sg.h : 251 204 27
linux/init/main.c : 17 4 0
linux/ipc/shm.c : 224 32 112
linux/kernel/fork.c : 32 16 2
linux/mm/memory.c : 9 2 1
linux/mm/mmap.c : 61 10 10
linux/net/README : 8 1 1
linux/net/appletalk/aarp.c : 67 13 13
linux/net/ipv6/tcp_ipv6.c : 7 1 0
linux/net/irda/Config.in : 15 0 2
linux/net/irda/Makefile : 25 2 10
linux/net/irda/af_irda.c : 1143 831 88
linux/net/irda/discovery.c : 245 245 0
linux/net/irda/ircomm/Makefile : 24 4 4
linux/net/irda/ircomm/attach.c : 360 0 360
linux/net/irda/ircomm/ircomm_common.c : 1836 879 386
linux/net/irda/ircomm/irvtd.c : 153 0 153
linux/net/irda/ircomm/irvtd_driver.c : 2569 988 875
linux/net/irda/irda_device.c : 479 137 140
linux/net/irda/iriap.c : 407 99 76
linux/net/irda/irias_object.c : 25 3 2
linux/net/irda/irlan/irlan_client.c : 213 64 60
linux/net/irda/irlan/irlan_common.c : 173 33 19
linux/net/irda/irlan/irlan_eth.c : 51 8 7
linux/net/irda/irlan/irlan_filter.c : 19 3 3
linux/net/irda/irlan/irlan_provider.c : 60 9 9
linux/net/irda/irlap.c : 239 47 39
linux/net/irda/irlap_event.c : 205 52 36
linux/net/irda/irlap_frame.c : 829 219 215
linux/net/irda/irlmp.c : 1475 533 424
linux/net/irda/irlmp_event.c : 285 74 66
linux/net/irda/irlmp_frame.c : 246 63 78
linux/net/irda/irlpt/irlpt_cli.c : 173 39 25
linux/net/irda/irlpt/irlpt_srvr.c : 170 39 39
linux/net/irda/irmod.c : 113 31 16
linux/net/irda/irobex/Config.in : 3 0 3
linux/net/irda/irobex/Makefile : 19 0 19
linux/net/irda/irobex/irobex.c : 1170 0 1170
linux/net/irda/irproc.c : 124 8 71
linux/net/irda/irqueue.c : 86 20 16
linux/net/irda/irttp.c : 756 221 134
linux/net/irda/wrapper.c : 72 17 13
linux/net/netlink/af_netlink.c : 7 0 1
linux/scripts/ver_linux : 11 1 4
--
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,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/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 34 - 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.6 ==============
if test -f 'patch-2.2.6' -a X"$1" != X"-c"; then
echo 'x - skipping patch-2.2.6 (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.6 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.6' &&
diff -u --recursive --new-file v2.2.5/linux/Documentation/Changes linux/Documentation/Changes
--- v2.2.5/linux/Documentation/Changes Tue Mar 23 14:35:46 1999
+++ linux/Documentation/Changes Mon Apr 12 16:18:27 1999
@@ -258,6 +258,11 @@
X The ISDN code in the stock 2.2 kernel may not work for you. If it
X doesn't, look in ftp://ftp.suse.com/pub/isdn4linux for updated versions.
X
+ In 2.0.x the kernel could be configured to drop source routed IP
+packets via a compile time configuration option. In 2.2.x, this has
+been replaced by a sysctl. See Documentation/networking/ip-sysctl.txt
+for more information.
+
X Memory
X ======
X
@@ -281,6 +286,20 @@
X 128 meg limit on IA32 swap partition sizes has been eliminated. To use
X larger swap spaces, you need the new mkswap found in util-linux. You
X also need to upgrade util-linux to get the latest version of mount.
+
+ Partitions on 2048 byte sectored media (certain magneto opticals
+most prominently) were broken throughout the whole of 2.1 kernel
+series, meaning that you will be unable to use 2.1-partitioned media on
+Linux 2.2. This is not a 2.2 bug - 2.2 finally does the right thing!
+[If you have to interchange media between Linux 2.1 and 2.2, your best
+bet is to not use partitions at all but create the filesystem on the
+raw device (e.g. /dev/sda) instead. This is also known as the
+superfloppy format.]
+
+ To properly create partitions on 2048 byte sectored media with Linux
+2.2, be sure to use no less than fdisk version 2.9i and invoke fdisk
+using '-b 2048' as an option.
+
X
X RPM
X ===
diff -u --recursive --new-file v2.2.5/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.5/linux/Documentation/Configure.help Mon Mar 29 11:09:11 1999
+++ linux/Documentation/Configure.help Mon Apr 12 09:58:57 1999
@@ -3956,8 +3956,8 @@
X tagged command queuing and fast synchronous data transfers up to 80
X MB/s with wide FAST-40 LVD devices and controllers.
X
- The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895
- supports FAST-40 transfers with Ultra2 LVD devices.
+ An additionnal driver named SYM53C8XX (a.k.a 896 driver) can also be
+ configured. See the help on the SYM53C8XX driver for more information.
X
X Note: there is another driver for the 53c8xx family of controllers
X ("NCR53c7,8xx SCSI support" above). If you want to use them both,
@@ -3967,6 +3967,30 @@
X
X Please read drivers/scsi/README.ncr53c8xx for more information.
X
+SYM53C8XX SCSI support
+CONFIG_SCSI_SYM53C8XX
+ The 896 driver for Linux (a.k.a. sym53c8xx) is derivated from the
+ ncr53c8xx driver and has been heavily reworked and enhanced to
+ fully support all the features of recent 53C8XX chips, notably the
+ hardware phase mismatch feature of the SYM53C896.
+
+ For that to be achieved without additionnal complexity, support of
+ old 8XX chips has been dropped. If your system uses either a
+ 810 rev. < 16, a 815, or a 825 rev. < 16 PCI SCSI processor, you must
+ use the generic NCR53C8XX driver or configure both the NCR53C8XX and
+ the SYM53C8XX drivers either as module or linked to the kernel image.
+
+ When both drivers are linked to the kernel, the SYM53C8XX driver is
+ called first at initialization and you can use the 'excl=ioaddr'
+ driver boot option to exclude attachement of adapters by the SYM53C8XX
+ driver. For instance, entering 'sym53c8xx=excl:0xb400,excl=0xc000' at
+ lilo prompt prevents adapters at io address 0xb400 and 0xc000 from
+ being attached by the SYM53C8XX driver, thus allowing the NCR53C8XX
+ driver to attach them. The 'excl' option is also supported by the
+ NCR53C8XX driver.
+
+ Please read drivers/scsi/README.ncr53c8xx for more information.
+
X synchronous data transfers frequency
X CONFIG_SCSI_NCR53C8XX_SYNC
X The SCSI Parallel Interface-2 Standard defines 4 classes of transfer
@@ -4079,6 +4103,17 @@
X
X The normal answer therefore is N.
X
+include support for the NCR PQS/PDS SCSI card
+CONFIG_SCSI_NCR53C8XX_PQS_PDS
+ This allows the driver to detect a special adapter produced by NCR
+ corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need
+ this if you do not have one of these adapters. However, since this
+ device is detected as a specific PCI device, this option is quite
+ safe. This option is only supported by the SYM53C8XX driver (not
+ by the NCR53C8XX driver).
+
+ The common answer here is N, but answering Y is safe.
+
X IBMMCA SCSI support
X CONFIG_SCSI_IBMMCA
X This is support for the IBM SCSI adapter found in many of the PS/2
@@ -7613,8 +7648,7 @@
X set, which covers most West European languages such as Albanian,
X Catalan, Danish, Dutch, English, Faeroese, Finnish, French, German,
X Galician, Irish, Icelandic, Italian, Norwegian, Portuguese, Spanish,
- Swedish, and Valencian. It is also the default for the US. If
- unsure, say Y.
+ and Swedish. It is also the default for the US. If unsure, say Y.
X
X nls iso8859-2
X CONFIG_NLS_ISO8859_2
@@ -7706,7 +7740,7 @@
X set, which covers most West European languages such as Albanian,
X Catalan, Danish, Dutch, English, Estonian, Faeroese, Finnish,
X French, German, Galician, Irish, Icelandic, Italian, Norwegian,
- Portuguese, Spanish, Swedish, and Valencian. Latin 9 is an update to
+ Portuguese, Spanish, and Swedish. Latin 9 is an update to
X Latin 1 (ISO 8859-1) that removes a handful of rarely used
X characters and instead adds support for Estonian, corrects the
X support for French and Finnish, and adds the new Euro character. If
diff -u --recursive --new-file v2.2.5/linux/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt
--- v2.2.5/linux/Documentation/fb/vesafb.txt Tue Feb 23 15:21:31 1999
+++ linux/Documentation/fb/vesafb.txt Mon Apr 12 09:57:34 1999
@@ -88,25 +88,63 @@
X with a broken console (and vesafb cannot do anything about this).
X
X
+Refresh rates
+=============
+
+There is no way to change the vesafb video mode and/or timings after
+booting linux. If you are not happy with the 60 Hz refresh rate, you
+have these options:
+
+ * configure and load the DOS-Tools for your the graphics board (if
+ available) and boot linux with loadlin.
+ * use a native driver (matroxfb/atyfb) instead if vesafb. If none
+ is available, write a new one!
+ * VBE 3.0 might work too. I havn't neither a gfx board with VBE 3.0
+ support nor the specs, so I havn't checked this yet. But maybe...
+
+
X Configuration
X =============
X
-You can pass kernel command line options to vesafb with
-"video=vesa:option1". Multiple options should be separated
-by comma. Accepted options:
-
-invers - no comment...
-redraw - scroll by redrawing the affected part of the screen
-ypan - enable display panning using the VESA protected mode
- interface. This enables the Shift-PgUp scrollback
- thing and greatly speeds up fullscreen scrolling.
- It is slower than "redraw" when scrolling only a halve
- screen. This is the default.
-ywrap - If your gfx board supports wrap-around, use this one
- instead of ypan.
-nopal - Don't use the protected mode interface for palette
- changes. vesafb will try the standard vga registers
- instead.
+The VESA BIOS provides protected mode interface for changing
+some parameters. vesafb can use it for palette changes and
+to pan the display. It is turned off by default becauce it
+seems not to work with some BIOS versions, but there are options
+to turn it on.
+
+You can pass options to vesafb using "video=vesa:option" on
+the kernel command line. Multiple options should be separated
+by comma, like this: "video=vesa:ypan,invers"
+
+Accepted options:
+
+invers no comment...
+
+ypan enable display panning using the VESA protected mode
+ interface. The visible screen is just a window of the
+ video memory, console scrolling is done by changing the
+ start of the window.
+ pro: * scrolling (fullscreen) is fast, becauce there is
+ no need to copy around data.
+ * You'll get scrollback (the Shift-PgUp thing),
+ the video memory can be used as scrollback buffer
+ kontra: * scrolling only parts of the screen causes some
+ ugly flicker effects (boot logo flickers for
+ example).
+
+ywrap Same as ypan, but assumes your gfx board can wrap-around
+ the video memory (i.e. starts reading from top if it
+ reaches the end of video memory). Faster than ypan.
+
+redraw scroll by redrawing the affected part of the screen, this
+ is the safe (and slow) default.
+
+
+vgapal Use the standard vga registers for palette changes.
+ This is the default.
+pmipal Use the protected mode interface for palette changes.
+
+mtrr setup memory type range registers for the vesafb framebuffer.
X
X
X Have fun!
@@ -114,7 +152,7 @@
X Gerd
X
X --
-Gerd Knorr <kra...@cs.tu-berlin.de>
+Gerd Knorr <kra...@goldbach.in-berlin.de>
X
X Minor (mostly typo) changes
X by Nico Schmoigl <schm...@rumms.uni-mannheim.de>
diff -u --recursive --new-file v2.2.5/linux/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX
--- v2.2.5/linux/Documentation/filesystems/00-INDEX Wed Jun 24 22:54:01 1998
+++ linux/Documentation/filesystems/00-INDEX Mon Apr 12 09:53:45 1999
@@ -20,6 +20,8 @@
X - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
X sysv-fs.txt
X - info on the SystemV/Coherent filesystem.
+ufs.txt
+ - info on the ufs filesystem.
X umsdos.txt
X - info on the umsdos extensions to the msdos filesystem.
X vfat.txt
diff -u --recursive --new-file v2.2.5/linux/Documentation/filesystems/ufs.txt linux/Documentation/filesystems/ufs.txt
--- v2.2.5/linux/Documentation/filesystems/ufs.txt Wed Dec 31 16:00:00 1969
+++ linux/Documentation/filesystems/ufs.txt Fri Apr 16 08:20:23 1999
@@ -0,0 +1,49 @@
+USING UFS
+=========
+
+mount -t ufs -o ufstype=type_of_ufs device dir
+
+
+UFS OPTIONS
+===========
+
+ufstype=type_of_ufs
+ UFS is a file system widely used in different operating systems.
+ The problem are differencies among implementations. Features of
+ some implementations are undocumented, so its hard to recognize
+ type of ufs automatically. That's why user must specify type of
+ ufs manually by mount option ufstype. Possible values are:
+
+ old old format of ufs
+ default value, supported os read-only
+
+ 44bsd used in FreeBSD, NetBSD, OpenBSD
+ supported os read-write
+
+ sun used in SunOS (Solaris)
+ supported as read-write
+
+ sunx86 used in SunOS for Intel (Solarisx86)
+ supported as read-write
+
+ nextstep
+ used in NextStep
+ supported as read-only
+
+ openstep
+ used in OpenStep
+ supported as read-only
+
+
+POSSIBLE PROBLEMS
+=================
+
+There is still bug in reallocation of fragment, in file fs/ufs/balloc.c,
+line 364. But it seem working on current buffer cache configuration.
+
+
+BUG REPORTS
+===========
+
+Any ufs bug report you can send to daniel...@email.cz (do not send
+partition tables bug reports.)
diff -u --recursive --new-file v2.2.5/linux/Documentation/sound/PCM1-pro linux/Documentation/sound/PCM1-pro
--- v2.2.5/linux/Documentation/sound/PCM1-pro Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/PCM1-pro Mon Apr 12 16:18:27 1999
@@ -0,0 +1,17 @@
+In Documentation/sound/README.OSS was a remark saying noone was sure the
+mixer on the PCM1-pro worked with the ACI driver. Well, it does.
+I've been using the drivers for the MAD16 and the driver for the mixer
+since kernel 2.0.32 with a MiroSound PCM1-pro and it works great.
+
+I've got it working with the following configuration:
+
+MAD16 audio I/O base = 530
+MAD16 audio IRQ = 7
+MAD16 Audio DMA = 1
+MAD16 MIDI I/O = 330
+MAD16 MIDI IRQ = 9
+
+And I've enabled the ACI mixer (miro PCM12) .
+
+
+Bas van der Linden.
diff -u --recursive --new-file v2.2.5/linux/Documentation/sound/mwave linux/Documentation/sound/mwave
--- v2.2.5/linux/Documentation/sound/mwave Thu Jul 16 18:09:22 1998
+++ linux/Documentation/sound/mwave Mon Apr 12 16:18:27 1999
@@ -1,14 +1,8 @@
X How to try to survive an IBM Mwave under Linux SB drivers
X
X
-* IBM refuses to provide documentation. If anyone can ever find out what
- MWD50430.EXE actually does to load firmware then this comedy could go
- away.
-
-* If you'd like to ask IBM why they don't release Mwave information.
- phone IBM (425-556-8822) and ask them why they still haven't
- released any documentation.
- [http://204.200.238.31/cgi-bin/link.pl?co=i&cl=/ts/ibm/contact.html]
++ IBM have now released documentation of sorts and Torsten is busy
+ trying to make the Mwave work. This is not however a trivial task.
X
X ----------------------------------------------------------------------------
X
diff -u --recursive --new-file v2.2.5/linux/Documentation/sysctl/README linux/Documentation/sysctl/README
--- v2.2.5/linux/Documentation/sysctl/README Fri Jan 8 22:35:59 1999
+++ linux/Documentation/sysctl/README Mon Apr 12 10:10:27 1999
@@ -1,5 +1,5 @@
-Documentation for /proc/sys/ kernel version 2.1.128
- (c) 1998, Rik van Riel <H.H.v...@phys.uu.nl>
+Documentation for /proc/sys/ kernel version 2.2.5
+ (c) 1998, 1999, Rik van Riel <ri...@nl.linux.org>
X
X 'Why', I hear you ask, 'would anyone even _want_ documentation
X for them sysctl files? If anybody really needs it, it's all in
@@ -12,9 +12,6 @@
X Furthermore, the programmers who built sysctl have built it to
X be actually used, not just for the fun of programming it :-)
X
-If you prefer HTML, feel free to visit the Linux-MM homepage
-<http://humbolt.geo.uu.nl/Linux-MM/>...
-
X ==============================================================
X
X Legal blurb:
@@ -34,7 +31,7 @@
X you're the last RTFMing person to screw up.
X
X In short, e-mail your suggestions, corrections and / or horror
-stories to: <H.H.v...@phys.uu.nl>
+stories to: <ri...@nl.linux.org>
X
X Rik van Riel.
X
@@ -68,6 +65,7 @@
X net/ networking stuff, for documentation look in:
X <linux/Documentation/networking/>
X proc/ <empty>
+sunrpc/ SUN Remote Procedure Call (NFS)
X vm/ memory management tuning
X buffer and cache management
X
diff -u --recursive --new-file v2.2.5/linux/Documentation/sysctl/fs.txt linux/Documentation/sysctl/fs.txt
--- v2.2.5/linux/Documentation/sysctl/fs.txt Thu Nov 19 09:56:27 1998
+++ linux/Documentation/sysctl/fs.txt Mon Apr 12 10:10:27 1999
@@ -1,12 +1,12 @@
-Documentation for /proc/sys/fs/* kernel version 2.1.128
- (c) 1998, Rik van Riel <H.H.v...@phys.uu.nl>
+Documentation for /proc/sys/fs/* kernel version 2.2.5
+ (c) 1998, 1999, Rik van Riel <ri...@nl.linux.org>
X
X For general info and legal blurb, please look in README.
X
X ==============================================================
X
X This file contains documentation for the sysctl files in
-/proc/sys/fs/ and is valid for Linux kernel version 2.1.
+/proc/sys/fs/ and is valid for Linux kernel version 2.2.
X
X The files in this directory can be used to tune and monitor
X miscellaneous and general things in the operation of the Linux
@@ -23,6 +23,8 @@
X - inode-max
X - inode-nr
X - inode-state
+- super-max
+- super-nr
X
X Documentation for the files in /proc/sys/fs/binfmt_misc is
X in Documentation/binfmt_misc.txt.
@@ -113,4 +115,12 @@
X system needs to prune the inode list instead of allocating
X more.
X
+==============================================================
+
+super-max & super-nr:
X
+These numbers control the maximum number of superblocks, and
+thus the maximum number of mounted filesystems the kernel
+can have. You only need to increase super-max if you need to
+mount more filesystems than the current value in super-max
+allows you to.
diff -u --recursive --new-file v2.2.5/linux/Documentation/sysctl/kernel.txt linux/Documentation/sysctl/kernel.txt
--- v2.2.5/linux/Documentation/sysctl/kernel.txt Fri Jan 1 12:58:14 1999
+++ linux/Documentation/sysctl/kernel.txt Mon Apr 12 10:10:27 1999
@@ -1,12 +1,12 @@
-Documentation for /proc/sys/kernel/* kernel version 2.1.128
- (c) 1998, Rik van Riel <H.H.v...@phys.uu.nl>
+Documentation for /proc/sys/kernel/* kernel version 2.2.5
+ (c) 1998, 1999, Rik van Riel <ri...@nl.linux.org>
X
X For general info and legal blurb, please look in README.
X
X ==============================================================
X
X This file contains documentation for the sysctl files in
-/proc/sys/kernel/ and is valid for Linux kernel version 2.1.
+/proc/sys/kernel/ and is valid for Linux kernel version 2.2.
X
X The files in this directory can be used to tune and monitor
X miscellaneous and general things in the operation of the Linux
@@ -24,6 +24,7 @@
X - htab-reclaim [ PPC only ]
X - java-appletviewer [ binfmt_java, obsolete ]
X - java-interpreter [ binfmt_java, obsolete ]
+- l2cr [ PPC only ]
X - modprobe ==> Documentation/kmod.txt
X - osrelease
X - ostype
@@ -32,6 +33,8 @@
X - printk
X - real-root-dev ==> Documentation/initrd.txt
X - reboot-cmd [ SPARC only ]
+- rtsig-nr
+- rtsig-max
X - sg-big-buff [ generic SCSI device (sg) ]
X - shmmax [ sysv ipc ]
X - version
@@ -90,6 +93,13 @@
X
X ==============================================================
X
+l2cr: (PPC only)
+
+This flag controls the L2 cache of G3 processor boards. If
+0, the cache is disabled. Enabled if nonzero.
+
+==============================================================
+
X osrelease, ostype & version:
X
X # cat osrelease
@@ -152,6 +162,16 @@
X ??? This seems to be a way to give an argument to the Sparc
X ROM/Flash boot loader. Maybe to tell it what to do after
X rebooting. ???
+
+==============================================================
+
+rtsig-max & rtsig-nr:
+
+The file rtsig-max can be used to tune the maximum number
+of POSIX realtime (queued) signals that can be outstanding
+in the system.
+
+Rtsig-nr shows the number of RT signals currently queued.
X
X ==============================================================
X
diff -u --recursive --new-file v2.2.5/linux/Documentation/sysctl/sunrpc.txt linux/Documentation/sysctl/sunrpc.txt
--- v2.2.5/linux/Documentation/sysctl/sunrpc.txt Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sysctl/sunrpc.txt Mon Apr 12 10:10:27 1999
@@ -0,0 +1,20 @@
+Documentation for /proc/sys/sunrpc/* kernel version 2.2.5
+ (c) 1998, 1999, Rik van Riel <ri...@nl.linux.org>
+
+For general info and legal blurb, please look in README.
+
+==============================================================
+
+This file contains the documentation for the sysctl files in
+/proc/sys/sunrpc and is valid for Linux kernel version 2.2.
+
+The files in this directory can be used to (re)set the debug
+flags of the SUN Remote Procedure Call (RPC) subsystem in
+the Linux kernel. This stuff is used for NFS, KNFSD and
+maybe a few other things as well.
+
+The files in there are used to control the debugging flags:
+rpc_debug, nfs_debug, nfsd_debug and nlm_debug.
+
+These flags are for kernel hackers only. You should read the
+source code in net/sunrpc/ for more information.
diff -u --recursive --new-file v2.2.5/linux/Documentation/sysctl/vm.txt linux/Documentation/sysctl/vm.txt
--- v2.2.5/linux/Documentation/sysctl/vm.txt Thu Nov 19 09:56:27 1998
+++ linux/Documentation/sysctl/vm.txt Mon Apr 12 10:10:27 1999
@@ -1,27 +1,30 @@
-Documentation for /proc/sys/vm/* kernel version 2.1.128
- (c) 1998, Rik van Riel <H.H.v...@phys.uu.nl>
+Documentation for /proc/sys/vm/* kernel version 2.2.5
+ (c) 1998, 1999, Rik van Riel <ri...@nl.linux.org>
X
X For general info and legal blurb, please look in README.
X
X ==============================================================
X
X This file contains the documentation for the sysctl files in
-/proc/sys/vm and is valid for Linux kernel version 2.1.
+/proc/sys/vm and is valid for Linux kernel version 2.2.
X
X The files in this directory can be used to tune the operation
X of the virtual memory (VM) subsystem of the Linux kernel, and
X one of the files (bdflush) also has a little influence on disk
X usage.
X
+Default values and initialization routines for most of these
+files can be found in mm/swap.c.
+
X Currently, these files are in /proc/sys/vm:
X - bdflush
X - buffermem
X - freepages
X - kswapd
X - overcommit_memory
+- page-cluster
X - pagecache
X - pagetable_cache
-- swapctl
X
X ==============================================================
X
@@ -100,12 +103,8 @@
X The values are:
X min_percent -- this is the minimum percentage of memory
X that should be spent on buffer memory
-borrow_percent -- when Linux is short on memory, and the
- buffer cache uses more memory than this,
- the MM subsystem will prune the buffercache
- more heavily than other memory
-max_percent -- this is the maximum amount of memory that
- can be used for buffer memory
+borrow_percent -- UNUSED
+max_percent -- UNUSED
X
X ==============================================================
X freepages:
@@ -162,40 +161,28 @@
X
X overcommit_memory:
X
-This file contains only one value. The following algorithm
-is used to decide if there's enough memory. If the value
-of overcommit_memory > 0, then there's always enough
-memory :-). This is a useful feature, since programs often
-malloc() huge amounts of memory 'just in case', while they
-only use a small part of it. Leaving this value at 0 will
-lead to the failure of such a huge malloc(), when in fact
-the system has enough memory for the program to run...
-On the other hand, enabling this feature can cause you to
-run out of memory and thrash the system to death, so large
-and/or important servers will want to set this value to 0.
+This value contains a flag that enables memory overcommitment.
+When this flag is 0, the kernel checks before each malloc()
+to see if there's enough memory left. If the flag is nonzero,
+the system pretends there's always enough memory.
X
-From linux/mm/mmap.c:
---------------------------------------------------------------
-static inline int vm_enough_memory(long pages)
-{
- /* This stupid algorithm decides whether we have enough memory:
- * while simple, it should work in most obvious cases. It's
- * easily fooled, but this should catch most mistakes.
- */
- long freepages;
-
- /* Sometimes we want to use more memory than we have. */
- if (sysctl_overcommit_memory)
- return 1;
-
- freepages = buffermem >> PAGE_SHIFT;
- freepages += page_cache_size;
- freepages >>= 1;
- freepages += nr_free_pages;
- freepages += nr_swap_pages;
- freepages -= num_physpages >> 4;
- return freepages > pages;
-}
+This feature can be very useful because there are a lot of
+programs that malloc() huge amounts of memory "just-in-case"
+and don't much of it.
+
+Look at: mm/mmap.c::vm_enough_memory() for more information.
+
+==============================================================
+
+page-cluster:
+
+The Linux VM subsystem avoids excessive disk seeks by reading
+multiple pages on a page fault. The number of pages it reads
+is dependant on the amount of memory in your machine.
+
+The number of pages the kernel reads in at once is equal to
+2 ^ page-cluster. Values above 2 ^ 5 don't make much sense
+for swap because we only cluster swap data in 32-page groups.
X
X ==============================================================
X
@@ -203,12 +190,17 @@
X
X This file does exactly the same as buffermem, only this
X file controls the struct page_cache, and thus controls
-the amount of memory allowed for memory mapping and generic
-caching of files.
+the amount of memory used for the page cache.
X
-You don't want the minimum level to be too low, otherwise
-your system might thrash when memory is tight or fragmentation
-is high...
+In 2.2, the page cache is used for 3 main purposes:
+- caching read() data from files
+- caching mmap()ed data and executable files
+- swap cache
+
+When your system is both deep in swap and high on cache,
+it probably means that a lot of the swaped data is being
+cached, making for more efficient swapping than possible
+with the 2.0 kernel.
X
X ==============================================================
X
@@ -226,63 +218,4 @@
X For large systems, the settings are probably OK. For normal
X systems they won't hurt a bit. For small systems (<16MB ram)
X it might be advantageous to set both values to 0.
-
-==============================================================
-
-swapctl:
-
-This file contains no less than 8 variables.
-All of these values are used by kswapd, and the usage can be
-found in linux/mm/vmscan.c.
-
-From linux/include/linux/swapctl.h:
---------------------------------------------------------------
-typedef struct swap_control_v5
-{
- unsigned int sc_max_page_age;
- unsigned int sc_page_advance;
- unsigned int sc_page_decline;
- unsigned int sc_page_initial_age;
- unsigned int sc_age_cluster_fract;
- unsigned int sc_age_cluster_min;
- unsigned int sc_pageout_weight;
- unsigned int sc_bufferout_weight;
-} swap_control_v5;
---------------------------------------------------------------
-
-The first four variables are used to keep track of Linux's
-page aging. Page aging is a bookkeeping method to keep track
-of which pages of memory are used often, and which pages can
-be swapped out without consequences.
-
-When a page is swapped in, it starts at sc_page_initial_age
-(default 3) and when the page is scanned by kswapd, its age
-is adjusted according to the following scheme:
-- if the page was used since the last time we scanned, its
- age is increased by sc_page_advance (default 3) up to a maximum
- of sc_max_page_age (default 20)
-- else (it wasn't used) its age is decreased by sc_page_decline
- (default 1)
-And when a page reaches age 0, it's ready to be swapped out.
-
-The next four variables can be used to control kswapd's
-aggressiveness in swapping out pages.
-
-sc_age_cluster_fract is used to calculate how many pages from
-a process are to be scanned by kswapd. The formula used is
-sc_age_cluster_fract/1024 * RSS, so if you want kswapd to scan
-the whole process, sc_age_cluster_fract needs to have a value
-of 1024. The minimum number of pages kswapd will scan is
-represented by sc_age_cluster_min, this is done so kswapd will
-also scan small processes.
-
-The values of sc_pageout_weight and sc_bufferout_weight are
-used to control how many tries kswapd will make in order
-to swapout one page / buffer. These values can be used to
-fine-tune the ratio between user pages and buffer/cache memory.
-When you find that your Linux system is swapping out too many
-process pages in order to satisfy buffer memory demands, you
-might want to either increase sc_bufferout_weight, or decrease
-the value of sc_pageout_weight.
-
X
diff -u --recursive --new-file v2.2.5/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.5/linux/MAINTAINERS Tue Mar 23 14:35:46 1999
+++ linux/MAINTAINERS Fri Apr 16 11:57:44 1999
@@ -395,7 +395,7 @@
X P: Dag Brattli
X M: Dag Brattli <da...@cs.uit.no>
X L: linux...@list.uit.no
-W: http://www.cs.uit.no/~dagb/irda/
+W: http://www.cs.uit.no/linux-irda/
X S: Maintained
X
X ISDN SUBSYSTEM
@@ -641,6 +641,13 @@
X P: Eberhard Moenkeberg
X M: emo...@gwdg.de
X L: linux-...@vger.rutgers.edu
+S: Maintained
+
+SCSI SG DRIVER
+P: Doug Gilbert
+M: dgil...@interlog.com
+L: linux...@vger.rutgers.edu
+W: http://www.torque.net/sg
X S: Maintained
X
X SCSI SUBSYSTEM
diff -u --recursive --new-file v2.2.5/linux/Makefile linux/Makefile
--- v2.2.5/linux/Makefile Mon Mar 29 11:09:11 1999
+++ linux/Makefile Fri Apr 16 08:20:23 1999
@@ -1,6 +1,6 @@
X VERSION = 2
X PATCHLEVEL = 2
-SUBLEVEL = 5
+SUBLEVEL = 6
X EXTRAVERSION =
X
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -343,7 +343,8 @@
X
X clean: archclean
X rm -f kernel/ksyms.lst include/linux/compile.h
- rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' -print`
+ rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' \
+ ! -regex '.*ksymoops/.*' -print`
X rm -f core `find . -type f -name 'core' -print`
X rm -f core `find . -name '.*.flags' -print`
X rm -f vmlinux System.map
@@ -367,6 +368,7 @@
X rm -f .version .config* config.in config.old
X rm -f scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp
X rm -f scripts/lxdialog/*.o scripts/lxdialog/lxdialog
+ rm -f scripts/ksymoops/*.o scripts/ksymoops/ksymoops
X rm -f .menuconfig.log
X rm -f include/asm
X rm -rf include/config
@@ -379,8 +381,8 @@
X
X distclean: mrproper
X rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
- -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
- -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
+ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
+ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
X
X backup: mrproper
X cd .. && tar cf - linux/ | gzip -9 > backup.gz
diff -u --recursive --new-file v2.2.5/linux/arch/alpha/lib/io.c linux/arch/alpha/lib/io.c
--- v2.2.5/linux/arch/alpha/lib/io.c Wed Sep 9 14:51:04 1998
+++ linux/arch/alpha/lib/io.c Thu Apr 15 05:42:31 1999
@@ -405,15 +405,16 @@
X * Copy data from "real" memory space to IO memory space.
X * This needs to be optimized.
X */
-void _memcpy_toio(unsigned long to, void * from, long count)
+void _memcpy_toio(unsigned long to, const void * from, long count)
X {
X /* Optimize co-aligned transfers. Everything else gets handled
X a byte at a time. */
+ /* FIXME -- align FROM. */
X
X if (count >= 8 && (to & 7) == ((long)from & 7)) {
X count -= 8;
X do {
- writeq(*(u64 *)from, to);
+ writeq(*(const u64 *)from, to);
X count -= 8;
X to += 8;
X from += 8;
@@ -424,7 +425,7 @@
X if (count >= 4 && (to & 3) == ((long)from & 3)) {
X count -= 4;
X do {
- writel(*(u32 *)from, to);
+ writel(*(const u32 *)from, to);
X count -= 4;
X to += 4;
X from += 4;
@@ -435,7 +436,7 @@
X if (count >= 2 && (to & 1) == ((long)from & 1)) {
X count -= 2;
X do {
- writew(*(u16 *)from, to);
+ writew(*(const u16 *)from, to);
X count -= 2;
X to += 2;
X from += 2;
@@ -444,7 +445,7 @@
X }
X
X while (count > 0) {
- writeb(*(u8 *) from, to);
+ writeb(*(const u8 *) from, to);
X count--;
X to++;
X from++;
diff -u --recursive --new-file v2.2.5/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.2.5/linux/arch/i386/defconfig Wed Mar 10 15:29:45 1999
+++ linux/arch/i386/defconfig Mon Apr 12 13:12:57 1999
@@ -174,12 +174,14 @@
X # CONFIG_SCSI_NCR53C406A is not set
X # CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
X CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4
X CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
X CONFIG_SCSI_NCR53C8XX_SYNC=20
X # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
X # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
X # CONFIG_SCSI_PCI2220I is not set
diff -u --recursive --new-file v2.2.5/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.2.5/linux/arch/i386/kernel/io_apic.c Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/kernel/io_apic.c Thu Apr 15 08:59:42 1999
@@ -293,7 +293,8 @@
X for (i = 0; i < mp_irq_entries; i++) {
X int lbus = mp_irqs[i].mpc_srcbus;
X
- if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA) &&
+ if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_EISA) &&
X (mp_irqs[i].mpc_irqtype == type) &&
X (mp_irqs[i].mpc_srcbusirq == 0x00))
X
@@ -326,20 +327,7 @@
X }
X
X /*
- * Unclear documentation on what a "conforming ISA interrupt" means.
- *
- * Should we, or should we not, take the ELCR register into account?
- * It's part of the EISA specification, but maybe it should only be
- * used if the interrupt is actually marked as EISA?
- *
- * Oh, well. Don't do it until somebody tells us what the right thing
- * to do is..
- */
-#undef USE_ELCR_TRIGGER_LEVEL
-#ifdef USE_ELCR_TRIGGER_LEVEL
-
-/*
- * ISA Edge/Level control register, ELCR
+ * EISA Edge/Level control register, ELCR
X */
X static int __init EISA_ELCR(unsigned int irq)
X {
@@ -349,18 +337,22 @@
X }
X printk("Broken MPtable reports ISA irq %d\n", irq);
X return 0;
-}
+}
X
-#define default_ISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_dstirq))
-#define default_ISA_polarity(idx) (0)
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value. If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
X
-#else
+#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_dstirq))
+#define default_EISA_polarity(idx) (0)
+
+/* ISA interrupts are always polarity zero edge triggered, even when
+ * listed as conforming in the MP table. */
X
X #define default_ISA_trigger(idx) (0)
X #define default_ISA_polarity(idx) (0)
X
-#endif
-
X static int __init MPBIOS_polarity(int idx)
X {
X int bus = mp_irqs[idx].mpc_srcbus;
@@ -380,6 +372,11 @@
X polarity = default_ISA_polarity(idx);
X break;
X }
+ case MP_BUS_EISA:
+ {
+ polarity = default_EISA_polarity(idx);
+ break;
+ }
X case MP_BUS_PCI: /* PCI pin */
X {
X polarity = 1;
@@ -439,6 +436,11 @@
X trigger = default_ISA_trigger(idx);
X break;
X }
+ case MP_BUS_EISA:
+ {
+ trigger = default_EISA_trigger(idx);
+ break;
+ }
X case MP_BUS_PCI: /* PCI pin, level */
X {
X trigger = 1;
@@ -503,6 +505,7 @@
X switch (mp_bus_id_to_type[bus])
X {
X case MP_BUS_ISA: /* ISA pin */
+ case MP_BUS_EISA:
X {
X irq = mp_irqs[idx].mpc_srcbusirq;
X break;
@@ -910,6 +913,8 @@
X static void __init construct_default_ISA_mptable(void)
X {
X int i, pos = 0;
+ const int bus_type = (mpc_default_type == 2 || mpc_default_type == 3 ||
+ mpc_default_type == 6) ? MP_BUS_EISA : MP_BUS_ISA;
X
X for (i = 0; i < 16; i++) {
X if (!IO_APIC_IRQ(i))
@@ -917,14 +922,14 @@
X
X mp_irqs[pos].mpc_irqtype = mp_INT;
X mp_irqs[pos].mpc_irqflag = 0; /* default */
- mp_irqs[pos].mpc_srcbus = MP_BUS_ISA;
+ mp_irqs[pos].mpc_srcbus = 0;
X mp_irqs[pos].mpc_srcbusirq = i;
X mp_irqs[pos].mpc_dstapic = 0;
X mp_irqs[pos].mpc_dstirq = i;
X pos++;
X }
X mp_irq_entries = pos;
- mp_bus_id_to_type[0] = MP_BUS_ISA;
+ mp_bus_id_to_type[0] = bus_type;
X
X /*
X * MP specification 1.4 defines some extra rules for default
@@ -1178,13 +1183,23 @@
X */
X if (i < 16)
X disable_8259A_irq(i);
- } else
+ } else {
+ if (!IO_APIC_IRQ(i))
+ continue;
+
X /*
- * we have no business changing low ISA
- * IRQs.
+ * Hmm.. We don't have an entry for this,
+ * so default to an old-fashioned 8259
+ * interrupt if we can..
X */
- if (IO_APIC_IRQ(i))
- irq_desc[i].handler = &no_irq_type;
+ if (i < 16) {
+ make_8259A_irq(i);
+ continue;
+ }
+
+ /* Strange. Oh, well.. */
+ irq_desc[i].handler = &no_irq_type;
+ }
X }
X init_IRQ_SMP();
X }
diff -u --recursive --new-file v2.2.5/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.2.5/linux/arch/i386/kernel/irq.c Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/kernel/irq.c Thu Apr 15 09:03:06 1999
@@ -151,10 +151,7 @@
X */
X static unsigned int cached_irq_mask = 0xffff;
X
-#define __byte(x,y) (((unsigned char *)&(y))[x])
-#define __word(x,y) (((unsigned short *)&(y))[x])
-#define __long(x,y) (((unsigned int *)&(y))[x])
-
+#define __byte(x,y) (((unsigned char *)&(y))[x])
X #define cached_21 (__byte(0,cached_irq_mask))
X #define cached_A1 (__byte(1,cached_irq_mask))
X
@@ -207,7 +204,7 @@
X void make_8259A_irq(unsigned int irq)
X {
X disable_irq(irq);
- __long(0,io_apic_irqs) &= ~(1<<irq);
+ io_apic_irqs &= ~(1<<irq);
X irq_desc[irq].handler = &i8259A_irq_type;
X enable_irq(irq);
X }
diff -u --recursive --new-file v2.2.5/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.2.5/linux/arch/i386/kernel/irq.h Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/kernel/irq.h Fri Apr 16 14:29:23 1999
@@ -115,6 +115,7 @@
X #define MAX_MP_BUSSES 32
X enum mp_bustype {
X MP_BUS_ISA,
+ MP_BUS_EISA,
X MP_BUS_PCI
X };
X extern int mp_bus_id_to_type [MAX_MP_BUSSES];
diff -u --recursive --new-file v2.2.5/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.2.5/linux/arch/i386/kernel/mca.c Fri Oct 23 22:01:19 1998
+++ linux/arch/i386/kernel/mca.c Thu Apr 15 05:42:40 1999
@@ -26,6 +26,9 @@
X * - Added the 'driver_loaded' flag in MCA_adapter
X * - Added an alternative implemention of ZP Gu's mca_find_unused_adapter
X *
+ * David Weinehall March 24th, 1999
+ * - Fixed the output of 'Driver Installed' in /proc/mca/pos
+ * - Made the Integrated Video & SCSI show up even if they have id 0000
X */
X
X #include <linux/types.h>
@@ -49,12 +52,12 @@
X * Other miscellaneous information follows.
X */
X
-typedef enum {
- MCA_ADAPTER_NORMAL = 0,
- MCA_ADAPTER_NONE = 1,
- MCA_ADAPTER_DISABLED = 2,
- MCA_ADAPTER_ERROR = 3
-} MCA_AdapterStatus;
+typedef enum {
+ MCA_ADAPTER_NORMAL = 0,
+ MCA_ADAPTER_NONE = 1,
+ MCA_ADAPTER_DISABLED = 2,
+ MCA_ADAPTER_ERROR = 3
+} MCA_AdapterStatus;
X
X struct MCA_adapter {
X MCA_AdapterStatus status; /* is there a valid adapter? */
@@ -69,16 +72,17 @@
X };
X
X struct MCA_info {
-/* one for each of the 8 possible slots, plus one for integrated SCSI
- and one for integrated video. */
+ /* one for each of the 8 possible slots, plus one for integrated SCSI
+ * and one for integrated video.
+ */
X
X struct MCA_adapter slot[MCA_NUMADAPTERS];
X
-/* two potential addresses for integrated SCSI adapter - this will
- * track which one we think it is
- */
+ /* two potential addresses for integrated SCSI adapter - this will
+ * track which one we think it is.
+ */
X
- unsigned char which_scsi;
+ unsigned char which_scsi;
X };
X
X /* The mca_info structure pointer. If MCA bus is present, the function
@@ -102,10 +106,10 @@
X
X #ifdef CONFIG_PROC_FS
X
-static void mca_do_proc_init( void );
-static int mca_default_procfn( char* buf, int slot );
+static void mca_do_proc_init(void);
+static int mca_default_procfn(char* buf, int slot);
X
-static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *);
+static ssize_t proc_mca_read(struct file*, char*, size_t, loff_t *);
X
X static struct file_operations proc_mca_operations = {
X NULL, /* array_lseek */
@@ -146,13 +150,13 @@
X
X /* Build the status info for the adapter */
X
-static void mca_configure_adapter_status( int slot ) {
+static void mca_configure_adapter_status(int slot) {
X mca_info->slot[slot].status = MCA_ADAPTER_NONE;
X
X mca_info->slot[slot].id = mca_info->slot[slot].pos[0]
X + (mca_info->slot[slot].pos[1] << 8);
X
- if( !mca_info->slot[slot].id ) {
+ if(!mca_info->slot[slot].id && slot < MCA_MAX_SLOT_NR) {
X
X /* id = 0x0000 usually indicates hardware failure,
X * however, ZP Gu (z...@castle.net> reports that his 9556
@@ -162,7 +166,7 @@
X mca_info->slot[slot].status = MCA_ADAPTER_ERROR;
X
X return;
- } else if( mca_info->slot[slot].id != 0xffff ) {
+ } else if(mca_info->slot[slot].id != 0xffff) {
X
X /* 0xffff usually indicates that there's no adapter,
X * however, some integrated adapters may have 0xffff as
@@ -174,21 +178,21 @@
X mca_info->slot[slot].status = MCA_ADAPTER_NORMAL;
X }
X
- if( (mca_info->slot[slot].id == 0xffff ||
- mca_info->slot[slot].id == 0x0000) && slot >= MCA_MAX_SLOT_NR ) {
+ if((mca_info->slot[slot].id == 0xffff ||
+ mca_info->slot[slot].id == 0x0000) && slot >= MCA_MAX_SLOT_NR) {
X int j;
X
- for( j = 2; j < 8; j++ ) {
- if( mca_info->slot[slot].pos[j] != 0xff ) {
+ for(j = 2; j < 8; j++) {
+ if(mca_info->slot[slot].pos[j] != 0xff) {
X mca_info->slot[slot].status = MCA_ADAPTER_NORMAL;
X break;
X }
X }
X }
X
- if( !(mca_info->slot[slot].pos[2] & MCA_ENABLED) ) {
+ if(!(mca_info->slot[slot].pos[2] & MCA_ENABLED)) {
X
- /* enabled bit is in pos 2 */
+ /* enabled bit is in POS 2 */
X
X mca_info->slot[slot].status = MCA_ADAPTER_DISABLED;
X }
@@ -198,22 +202,22 @@
X
X __initfunc(void mca_init(void))
X {
- unsigned int i, j;
+ unsigned int i, j;
X unsigned long flags;
X
X /* WARNING: Be careful when making changes here. Putting an adapter
- * and the motherboard simultaneously into setup mode may result in
- * damage to chips (according to The Indispensible PC Hardware Book
- * by Hans-Peter Messmer). Also, we disable system interrupts (so
+ * and the motherboard simultaneously into setup mode may result in
+ * damage to chips (according to The Indispensible PC Hardware Book
+ * by Hans-Peter Messmer). Also, we disable system interrupts (so
X * that we are not disturbed in the middle of this).
X */
X
X /* Make sure the MCA bus is present */
X
- if (!MCA_bus)
+ if(!MCA_bus)
X return;
- printk( "Micro Channel bus detected.\n" );
- save_flags( flags );
+ printk("Micro Channel bus detected.\n");
+ save_flags(flags);
X cli();
X
X /* Allocate MCA_info structure (at address divisible by 8) */
@@ -225,67 +229,68 @@
X outb_p(0, MCA_ADAPTER_SETUP_REG);
X
X /* Put motherboard into video setup mode, read integrated video
- * pos registers, and turn motherboard setup off.
+ * POS registers, and turn motherboard setup off.
X */
X
X outb_p(0xdf, MCA_MOTHERBOARD_SETUP_REG);
X mca_info->slot[MCA_INTEGVIDEO].name[0] = 0;
- for (j=0; j<8; j++) {
- mca_info->slot[MCA_INTEGVIDEO].pos[j] = inb_p(MCA_POS_REG(j));
+ for(j=0; j<8; j++) {
+ mca_info->slot[MCA_INTEGVIDEO].pos[j] = inb_p(MCA_POS_REG(j));
X }
X mca_configure_adapter_status(MCA_INTEGVIDEO);
X
X /* Put motherboard into scsi setup mode, read integrated scsi
- * pos registers, and turn motherboard setup off.
+ * POS registers, and turn motherboard setup off.
X *
- * It seems there are two possible SCSI registers. Martin says that
+ * It seems there are two possible SCSI registers. Martin says that
X * for the 56,57, 0xf7 is the one, but fails on the 76.
X * Alfredo (ap...@vnet.ibm.com) says
- * 0xfd works on his machine. We'll try both of them. I figure it's
- * a good bet that only one could be valid at a time. This could
+ * 0xfd works on his machine. We'll try both of them. I figure it's
+ * a good bet that only one could be valid at a time. This could
X * screw up though if one is used for something else on the other
X * machine.
X */
X
X outb_p(0xf7, MCA_MOTHERBOARD_SETUP_REG);
X mca_info->slot[MCA_INTEGSCSI].name[0] = 0;
- for (j=0; j<8; j++) {
- if( (mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j))) != 0xff )
+ for(j=0; j<8; j++) {
+ if((mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j))) != 0xff)
X {
- /* 0xff all across means no device. 0x00 means something's
- * broken, but a device is probably there. However, if you get
- * 0x00 from a motherboard register it won't matter what we
- * find. For the record, on the 57SLC, the integrated SCSI
- * adapter has 0xffff for the adapter ID, but nonzero for
- * other registers.
+ /* 0xff all across means no device. 0x00 means
+ * something's broken, but a device is probably there.
+ * However, if you get 0x00 from a motherboard
+ * register it won't matter what we find. For the
+ * record, on the 57SLC, the integrated SCSI
+ * adapter has 0xffff for the adapter ID, but
+ * nonzero for other registers.
X */
X
X mca_info->which_scsi = 0xf7;
X }
X }
- if( !mca_info->which_scsi ) {
+ if(!mca_info->which_scsi) {
X
X /* Didn't find it at 0xf7, try somewhere else... */
X mca_info->which_scsi = 0xfd;
X
X outb_p(0xfd, MCA_MOTHERBOARD_SETUP_REG);
- for (j=0; j<8; j++)
- mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j));
+ for(j=0; j<8; j++)
+ mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j));
X }
X mca_configure_adapter_status(MCA_INTEGSCSI);
X
- /* turn off motherboard setup */
+ /* Turn off motherboard setup */
X
X outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
X
X /* Now loop over MCA slots: put each adapter into setup mode, and
- * read its pos registers. Then put adapter setup off.
+ * read its POS registers. Then put adapter setup off.
X */
X
- for (i=0; i<MCA_MAX_SLOT_NR; i++) {
+ for(i=0; i<MCA_MAX_SLOT_NR; i++) {
X outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
- for (j=0; j<8; j++) {
- mca_info->slot[i].pos[j]=inb_p(MCA_POS_REG(j));
+ for(j=0; j<8; j++) {
+ mca_info->slot[i].pos[j]=inb_p(MCA_POS_REG(j));
X }
X mca_info->slot[i].name[0] = 0;
X mca_info->slot[i].driver_loaded = 0;
@@ -295,7 +300,7 @@
X
X /* Enable interrupts and return memory start */
X
- restore_flags( flags );
+ restore_flags(flags);
X
X request_region(0x60,0x01,"system control port B (MCA)");
X request_region(0x90,0x01,"arbitration (MCA)");
@@ -312,89 +317,90 @@
X
X /*--------------------------------------------------------------------*/
X
-static void mca_handle_nmi_slot( int slot, int check_flag )
+static void mca_handle_nmi_slot(int slot, int check_flag)
X {
- if( slot < MCA_MAX_SLOT_NR ) {
- printk( "NMI: caused by MCA adapter in slot %d (%s)\n", slot+1,
- mca_info->slot[slot].name );
- } else if( slot == MCA_INTEGSCSI ) {
- printk( "NMI: caused by MCA integrated SCSI adapter (%s)\n",
- mca_info->slot[slot].name );
- } else if( slot == MCA_INTEGVIDEO ) {
- printk( "NMI: caused by MCA integrated video adapter (%s)\n",
- mca_info->slot[slot].name );
- }
-
- /* more info available in pos 6 and 7? */
-
- if( check_flag ) {
- unsigned char pos6, pos7;
-
- pos6 = mca_read_pos( slot, 6 );
- pos7 = mca_read_pos( slot, 7 );
-
- printk( "NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7 );
- }
-
-} /* mca_handle_nmi_slot */
-
-/*--------------------------------------------------------------------*/
+ if(slot < MCA_MAX_SLOT_NR) {
+ printk("NMI: caused by MCA adapter in slot %d (%s)\n", slot+1,
+ mca_info->slot[slot].name);
+ } else if(slot == MCA_INTEGSCSI) {
+ printk("NMI: caused by MCA integrated SCSI adapter (%s)\n",
+ mca_info->slot[slot].name);
+ } else if(slot == MCA_INTEGVIDEO) {
+ printk("NMI: caused by MCA integrated video adapter (%s)\n",
+ mca_info->slot[slot].name);
+ }
+
+ /* More info available in POS 6 and 7? */
+
+ if(check_flag) {
+ unsigned char pos6, pos7;
+
+ pos6 = mca_read_pos(slot, 6);
+ pos7 = mca_read_pos(slot, 7);
+
+ printk("NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7);
+ }
+
+} /* mca_handle_nmi_slot */
+
+/*--------------------------------------------------------------------*/
X
-void mca_handle_nmi( void )
+void mca_handle_nmi(void)
X {
X
X int i;
- unsigned char pos5;
-
- /* First try - scan the various adapters and see if a specific
- * adapter was responsible for the error
- */
-
- for( i = 0; i < MCA_NUMADAPTERS; i += 1 ) {
-
- /* bit 7 of POS 5 is reset when this adapter has a hardware
- * error. bit 7 it reset if there's error information
- * available in pos 6 and 7. */
-
- pos5 = mca_read_pos( i, 5 );
-
- if( !(pos5 & 0x80) ) {
- mca_handle_nmi_slot( i, !(pos5 & 0x40) );
- return;
- }
- }
-
- /* if I recall correctly, there's a whole bunch of other things that
- * we can do to check for NMI problems, but that's all I know about
+ unsigned char pos5;
+
+ /* First try - scan the various adapters and see if a specific
+ * adapter was responsible for the error.
+ */
+
+ for(i = 0; i < MCA_NUMADAPTERS; i++) {
+
+ /* Bit 7 of POS 5 is reset when this adapter has a hardware
+ * error. Bit 7 it reset if there's error information
+ * available in POS 6 and 7.
+ */
+
+ pos5 = mca_read_pos(i, 5);
+
+ if(!(pos5 & 0x80)) {
+ mca_handle_nmi_slot(i, !(pos5 & 0x40));
+ return;
+ }
+ }
+
+ /* If I recall correctly, there's a whole bunch of other things that
+ * we can do to check for NMI problems, but that's all I know about
X * at the moment.
- */
+ */
X
- printk( "NMI generated from unknown source!\n" );
-} /* mca_handle_nmi */
+ printk("NMI generated from unknown source!\n");
+} /* mca_handle_nmi */
X
X /*--------------------------------------------------------------------*/
X
-int mca_find_adapter( int id, int start )
+int mca_find_adapter(int id, int start)
X {
- if( mca_info == 0 || id == 0 || id == 0xffff ) {
+ if(mca_info == 0 || id == 0 || id == 0xffff) {
X return MCA_NOTFOUND;
X }
X
- for( ; start >= 0 && start < MCA_NUMADAPTERS; start += 1 ) {
+ for(; start >= 0 && start < MCA_NUMADAPTERS; start++) {
X
- /* not sure about this. There's no point in returning
+ /* Not sure about this. There's no point in returning
X * adapters that aren't enabled, since they can't actually
- * be used. However, they might be needed for statistical
+ * be used. However, they might be needed for statistical
X * purposes or something... But if that is the case, the
X * user is free to write a routine that manually iterates
X * through the adapters.
X */
X
- if( mca_info->slot[start].status == MCA_ADAPTER_DISABLED ) {
+ if(mca_info->slot[start].status == MCA_ADAPTER_DISABLED) {
X continue;
X }
X
- if( id == mca_info->slot[start].id ) {
+ if(id == mca_info->slot[start].id) {
X return start;
X }
X }
@@ -404,28 +410,28 @@
X
X /*--------------------------------------------------------------------*/
X
-int mca_find_unused_adapter( int id, int start )
+int mca_find_unused_adapter(int id, int start)
X {
- if( mca_info == 0 || id == 0 || id == 0xffff ) {
+ if(mca_info == 0 || id == 0 || id == 0xffff) {
X return MCA_NOTFOUND;
X }
X
- for( ; start >= 0 && start < MCA_NUMADAPTERS; start += 1 ) {
+ for(; start >= 0 && start < MCA_NUMADAPTERS; start++) {
X
- /* not sure about this. There's no point in returning
+ /* not sure about this. There's no point in returning
X * adapters that aren't enabled, since they can't actually
- * be used. However, they might be needed for statistical
+ * be used. However, they might be needed for statistical
X * purposes or something... But if that is the case, the
X * user is free to write a routine that manually iterates
X * through the adapters.
X */
X
- if( mca_info->slot[start].status == MCA_ADAPTER_DISABLED ||
- mca_info->slot[start].driver_loaded ) {
+ if(mca_info->slot[start].status == MCA_ADAPTER_DISABLED ||
+ mca_info->slot[start].driver_loaded) {
X continue;
X }
X
- if( id == mca_info->slot[start].id ) {
+ if(id == mca_info->slot[start].id) {
X return start;
X }
X }
@@ -435,68 +441,68 @@
X
X /*--------------------------------------------------------------------*/
X
-unsigned char mca_read_stored_pos( int slot, int reg )
+unsigned char mca_read_stored_pos(int slot, int reg)
X {
- if( slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0 ) return 0;
- if( reg < 0 || reg >= 8 ) return 0;
+ if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0) return 0;
+ if(reg < 0 || reg >= 8) return 0;
X return mca_info->slot[slot].pos[reg];
X } /* mca_read_stored_pos() */
X
X /*--------------------------------------------------------------------*/
X
-unsigned char mca_read_pos( int slot, int reg )
+unsigned char mca_read_pos(int slot, int reg)
X {
X unsigned int byte = 0;
X unsigned long flags;
X
- if( slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0 ) return 0;
- if( reg < 0 || reg >= 8 ) return 0;
+ if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0) return 0;
+ if(reg < 0 || reg >= 8) return 0;
X
- save_flags( flags );
+ save_flags(flags);
X cli();
X
- /* make sure motherboard setup is off */
+ /* Make sure motherboard setup is off */
X
X outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
X
- /* read in the appropriate register */
+ /* Read in the appropriate register */
X
- if( slot == MCA_INTEGSCSI && mca_info->which_scsi ) {
+ if(slot == MCA_INTEGSCSI && mca_info->which_scsi) {
X
- /* disable adapter setup, enable motherboard setup */
+ /* Disable adapter setup, enable motherboard setup */
X
X outb_p(0, MCA_ADAPTER_SETUP_REG);
X outb_p(mca_info->which_scsi, MCA_MOTHERBOARD_SETUP_REG);
X
X byte = inb_p(MCA_POS_REG(reg));
X outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
- } else if( slot == MCA_INTEGVIDEO ) {
+ } else if(slot == MCA_INTEGVIDEO) {
X
- /* disable adapter setup, enable motherboard setup */
+ /* Disable adapter setup, enable motherboard setup */
X
X outb_p(0, MCA_ADAPTER_SETUP_REG);
X outb_p(0xdf, MCA_MOTHERBOARD_SETUP_REG);
X
X byte = inb_p(MCA_POS_REG(reg));
X outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
- } else if( slot < MCA_MAX_SLOT_NR ) {
+ } else if(slot < MCA_MAX_SLOT_NR) {
X
- /* make sure motherboard setup is off */
+ /* Make sure motherboard setup is off */
X
X outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
X
- /* read the appropriate register */
+ /* Read the appropriate register */
X
X outb_p(0x8|(slot&0xf), MCA_ADAPTER_SETUP_REG);
X byte = inb_p(MCA_POS_REG(reg));
X outb_p(0, MCA_ADAPTER_SETUP_REG);
X }
X
- /* make sure the stored values are consistent, while we're here */
+ /* Make sure the stored values are consistent, while we're here */
X
X mca_info->slot[slot].pos[reg] = byte;
X
- restore_flags( flags );
+ restore_flags(flags);
X
X return byte;
X } /* mca_read_pos() */
@@ -513,44 +519,47 @@
X * screws up.
X */
X
-void mca_write_pos( int slot, int reg, unsigned char byte )
+void mca_write_pos(int slot, int reg, unsigned char byte)
X {
X unsigned long flags;
X
- if( slot < 0 || slot >= MCA_MAX_SLOT_NR ) return;
- if( reg < 0 || reg >= 8 ) return;
- if (mca_info == 0 ) return;
+ if(slot < 0 || slot >= MCA_MAX_SLOT_NR)
+ return;
+ if(reg < 0 || reg >= 8)
+ return;
+ if(mca_info == 0)
+ return;
X
- save_flags( flags );
+ save_flags(flags);
X cli();
X
- /* make sure motherboard setup is off */
+ /* Make sure motherboard setup is off */
X
X outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
X
- /* read in the appropriate register */
+ /* Read in the appropriate register */
X
X outb_p(0x8|(slot&0xf), MCA_ADAPTER_SETUP_REG);
- outb_p( byte, MCA_POS_REG(reg) );
+ outb_p(byte, MCA_POS_REG(reg));
X outb_p(0, MCA_ADAPTER_SETUP_REG);
X
- restore_flags( flags );
+ restore_flags(flags);
X
- /* update the global register list, while we have the byte */
+ /* Update the global register list, while we have the byte */
X
X mca_info->slot[slot].pos[reg] = byte;
X } /* mca_write_pos() */
X
X /*--------------------------------------------------------------------*/
X
-void mca_set_adapter_name( int slot, char* name )
+void mca_set_adapter_name(int slot, char* name)
X {
- if( mca_info == 0 ) return;
+ if(mca_info == 0) return;
X
- if( slot >= 0 && slot < MCA_NUMADAPTERS ) {
- if( name != NULL ) {
- strncpy( mca_info->slot[slot].name, name,
- sizeof(mca_info->slot[slot].name)-1 );
+ if(slot >= 0 && slot < MCA_NUMADAPTERS) {
+ if(name != NULL) {
+ strncpy(mca_info->slot[slot].name, name,
+ sizeof(mca_info->slot[slot].name)-1);
X mca_info->slot[slot].name[
X sizeof(mca_info->slot[slot].name)-1] = 0;
X } else {
@@ -559,61 +568,61 @@
X }
X }
X
-void mca_set_adapter_procfn( int slot, MCA_ProcFn procfn, void* dev)
SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi
echo 'End of part 01'
echo 'File patch-2.2.6 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part02

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


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

# file patch-2.2.6 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.6'
else
echo 'x - continuing with patch-2.2.6'


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

+void mca_set_adapter_procfn(int slot, MCA_ProcFn procfn, void* dev)


X {
- if( mca_info == 0 ) return;
+ if(mca_info == 0) return;
X
- if( slot >= 0 && slot < MCA_NUMADAPTERS ) {

+ if(slot >= 0 && slot < MCA_NUMADAPTERS) {

X mca_info->slot[slot].procfn = procfn;
X mca_info->slot[slot].dev = dev;
X }
X }
X
-int mca_is_adapter_used( int slot )
+int mca_is_adapter_used(int slot)
X {
X return mca_info->slot[slot].driver_loaded;
X }
X
-int mca_mark_as_used( int slot )
+int mca_mark_as_used(int slot)
X {
X if(mca_info->slot[slot].driver_loaded) return 1;
X mca_info->slot[slot].driver_loaded = 1;
X return 0;
X }
X
-void mca_mark_as_unused( int slot )
+void mca_mark_as_unused(int slot)
X {
X mca_info->slot[slot].driver_loaded = 0;
X }
X
-char *mca_get_adapter_name( int slot )
+char *mca_get_adapter_name(int slot)
X {
- if( mca_info == 0 ) return 0;
+ if(mca_info == 0) return 0;


X
- if( slot >= 0 && slot < MCA_NUMADAPTERS ) {

+ if(slot >= 0 && slot < MCA_NUMADAPTERS) {

X return mca_info->slot[slot].name;
X }
X
X return 0;
X }
X
-int mca_isadapter( int slot )
+int mca_isadapter(int slot)
X {
- if( mca_info == 0 ) return 0;
+ if(mca_info == 0) return 0;


X
- if( slot >= 0 && slot < MCA_NUMADAPTERS ) {

- return (( mca_info->slot[slot].status == MCA_ADAPTER_NORMAL )
- || (mca_info->slot[slot].status == MCA_ADAPTER_DISABLED ) );


+ if(slot >= 0 && slot < MCA_NUMADAPTERS) {

+ return ((mca_info->slot[slot].status == MCA_ADAPTER_NORMAL)
+ || (mca_info->slot[slot].status == MCA_ADAPTER_DISABLED));
X }
X
X return 0;
X }
X
-int mca_isenabled( int slot )
+int mca_isenabled(int slot)
X {
- if( mca_info == 0 ) return 0;
+ if(mca_info == 0) return 0;


X
- if( slot >= 0 && slot < MCA_NUMADAPTERS ) {

+ if(slot >= 0 && slot < MCA_NUMADAPTERS) {

X return (mca_info->slot[slot].status == MCA_ADAPTER_NORMAL);
X }
X
@@ -624,39 +633,37 @@


X
X #ifdef CONFIG_PROC_FS
X

-int get_mca_info(char *buf)
+int get_mca_info(char *buf)
X {
- int i, j, len = 0;
+ int i, j, len = 0;
X
- if( MCA_bus && mca_info != 0 )
+ if(MCA_bus && mca_info != 0)
X {
- /* Format pos registers of eight MCA slots */
+ /* Format POS registers of eight MCA slots */


X
- for (i=0; i<MCA_MAX_SLOT_NR; i++)
+ for(i=0; i<MCA_MAX_SLOT_NR; i++)

X {
X len += sprintf(buf+len, "Slot %d: ", i+1);


- for (j=0; j<8; j++)

+ for(j=0; j<8; j++)

X len += sprintf(buf+len, "%02x ", mca_info->slot[i].pos[j]);
- len += sprintf( buf+len, " %s\n", mca_info->slot[i].name );
- }
+ len += sprintf(buf+len, " %s\n", mca_info->slot[i].name);
+ }
X
- /* Format pos registers of integrated video subsystem */
+ /* Format POS registers of integrated video subsystem */
X
X len += sprintf(buf+len, "Video : ");


- for (j=0; j<8; j++)

+ for(j=0; j<8; j++)

X len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]);
- len += sprintf( buf+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name );
+ len += sprintf(buf+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name);
X
- /* Format pos registers of integrated SCSI subsystem */
+ /* Format POS registers of integrated SCSI subsystem */
X
X len += sprintf(buf+len, "SCSI : ");


- for (j=0; j<8; j++)

+ for(j=0; j<8; j++)

X len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]);
- len += sprintf( buf+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name );
- }
- else
- {
- /* Leave it empty if MCA not detected - this should *never*
+ len += sprintf(buf+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name);
+ } else {
+ /* Leave it empty if MCA not detected - this should *never*
X * happen!
X */
X }
@@ -667,119 +674,119 @@
X
X /*--------------------------------------------------------------------*/
X
-__initfunc(void mca_do_proc_init( void ))
+__initfunc(void mca_do_proc_init(void))
X {
X int i = 0;
X struct proc_dir_entry* node = 0;
X
- if( mca_info == 0 ) return; /* should never happen */
+ if(mca_info == 0) return; /* Should never happen */
X
- proc_register( &proc_mca, &(struct proc_dir_entry) {
+ proc_register(&proc_mca, &(struct proc_dir_entry) {
X PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
- 1, 0, 0, 0, &proc_mca_inode_operations,} );
+ 1, 0, 0, 0, &proc_mca_inode_operations,});
X
- proc_register( &proc_mca, &(struct proc_dir_entry) {
+ proc_register(&proc_mca, &(struct proc_dir_entry) {
X PROC_MCA_MACHINE, 7, "machine", S_IFREG|S_IRUGO,
- 1, 0, 0, 0, &proc_mca_inode_operations,} );
+ 1, 0, 0, 0, &proc_mca_inode_operations,});
X
- /* initialize /proc/mca entries for existing adapters */
+ /* Initialize /proc/mca entries for existing adapters */
X

- for( i = 0; i < MCA_NUMADAPTERS; i += 1 ) {

+ for(i = 0; i < MCA_NUMADAPTERS; i++) {

X mca_info->slot[i].procfn = 0;
X mca_info->slot[i].dev = 0;
X
- if( ! mca_isadapter( i ) ) continue;
+ if(!mca_isadapter(i)) continue;
X node = kmalloc(sizeof(struct proc_dir_entry), GFP_ATOMIC);
X
- if( i < MCA_MAX_SLOT_NR ) {
+ if(i < MCA_MAX_SLOT_NR) {
X node->low_ino = PROC_MCA_SLOT + i;
- node->namelen = sprintf( mca_info->slot[i].procname,
- "slot%d", i+1 );
- } else if( i == MCA_INTEGVIDEO ) {
+ node->namelen = sprintf(mca_info->slot[i].procname,
+ "slot%d", i+1);
+ } else if(i == MCA_INTEGVIDEO) {
X node->low_ino = PROC_MCA_VIDEO;
- node->namelen = sprintf( mca_info->slot[i].procname,
- "video" );
- } else if( i == MCA_INTEGSCSI ) {
+ node->namelen = sprintf(mca_info->slot[i].procname,
+ "video");
+ } else if(i == MCA_INTEGSCSI) {
X node->low_ino = PROC_MCA_SCSI;
- node->namelen = sprintf( mca_info->slot[i].procname,
- "scsi" );
+ node->namelen = sprintf(mca_info->slot[i].procname,
+ "scsi");
X }
X node->name = mca_info->slot[i].procname;
X node->mode = S_IFREG | S_IRUGO;
X node->ops = &proc_mca_inode_operations;
- proc_register( &proc_mca, node );
+ proc_register(&proc_mca, node);
X }
X
X } /* mca_do_proc_init() */
X
X /*--------------------------------------------------------------------*/
X
-int mca_default_procfn( char* buf, int slot )
+int mca_default_procfn(char* buf, int slot)
X {
X int len = 0, i;
X
- /* this really shouldn't happen... */
+ /* This really shouldn't happen... */
X
- if( mca_info == 0 ) {
+ if(mca_info == 0) {
X *buf = 0;
X return 0;
X }
X
- /* print out the basic information */
+ /* Print out the basic information */
X
- if( slot < MCA_MAX_SLOT_NR ) {
- len += sprintf( buf+len, "Slot: %d\n", slot+1 );


- } else if( slot == MCA_INTEGSCSI ) {

- len += sprintf( buf+len, "Integrated SCSI Adapter\n" );


- } else if( slot == MCA_INTEGVIDEO ) {

- len += sprintf( buf+len, "Integrated Video Adapter\n" );
+ if(slot < MCA_MAX_SLOT_NR) {
+ len += sprintf(buf+len, "Slot: %d\n", slot+1);


+ } else if(slot == MCA_INTEGSCSI) {

+ len += sprintf(buf+len, "Integrated SCSI Adapter\n");


+ } else if(slot == MCA_INTEGVIDEO) {

+ len += sprintf(buf+len, "Integrated Video Adapter\n");
X }
- if( mca_info->slot[slot].name[0] ) {
+ if(mca_info->slot[slot].name[0]) {
X
- /* drivers might register a name without /proc handler... */
+ /* Drivers might register a name without /proc handler... */
X
- len += sprintf( buf+len, "Adapter Name: %s\n",


- mca_info->slot[slot].name );

+ len += sprintf(buf+len, "Adapter Name: %s\n",


+ mca_info->slot[slot].name);

X } else {
- len += sprintf( buf+len, "Adapter Name: Unknown\n" );
+ len += sprintf(buf+len, "Adapter Name: Unknown\n");
X }
- len += sprintf( buf+len, "Id: %02x%02x\n",
- mca_info->slot[slot].pos[1], mca_info->slot[slot].pos[0] );
- len += sprintf( buf+len, "Enabled: %s\nPOS: ",
- mca_isenabled(slot) ? "Yes" : "No" );
- len += sprintf( buf+len, "Driver Installed: %s\n",
- mca_is_adapter_used(slot) ? "Yes" : "No" );
- for (i=0; i<8; i++) {
+ len += sprintf(buf+len, "Id: %02x%02x\n",
+ mca_info->slot[slot].pos[1], mca_info->slot[slot].pos[0]);
+ len += sprintf(buf+len, "Enabled: %s\nPOS: ",
+ mca_isenabled(slot) ? "Yes" : "No");
+ for(i=0; i<8; i++) {
X len += sprintf(buf+len, "%02x ", mca_info->slot[slot].pos[i]);
X }
+ len += sprintf(buf+len, "\nDriver Installed: %s",
+ mca_is_adapter_used(slot) ? "Yes" : "No");
X buf[len++] = '\n';
X buf[len] = 0;
X
X return len;
X } /* mca_default_procfn() */
X
-static int get_mca_machine_info( char* buf )
+static int get_mca_machine_info(char* buf)
X {
X int len = 0;
X
- len += sprintf( buf+len, "Model Id: 0x%x\n", machine_id );
- len += sprintf( buf+len, "Submodel Id: 0x%x\n", machine_submodel_id );
- len += sprintf( buf+len, "BIOS Revision: 0x%x\n", BIOS_revision );
+ len += sprintf(buf+len, "Model Id: 0x%x\n", machine_id);
+ len += sprintf(buf+len, "Submodel Id: 0x%x\n", machine_submodel_id);
+ len += sprintf(buf+len, "BIOS Revision: 0x%x\n", BIOS_revision);
X
X return len;
X }
X
-static int mca_fill( char* page, int pid, int type, char** start,
+static int mca_fill(char* page, int pid, int type, char** start,
X loff_t *offset, int length)
X {
X int len = 0;
X int slot = 0;
X
- switch( type ) {
+ switch(type) {
X case PROC_MCA_REGISTERS:
- return get_mca_info( page );
+ return get_mca_info(page);
X case PROC_MCA_MACHINE:
- return get_mca_machine_info( page );
+ return get_mca_machine_info(page);
X case PROC_MCA_VIDEO:
X slot = MCA_INTEGVIDEO;
X break;
@@ -787,24 +794,24 @@
X slot = MCA_INTEGSCSI;
X break;
X default:
- if( type < PROC_MCA_SLOT || type >= PROC_MCA_LAST ) {
+ if(type < PROC_MCA_SLOT || type >= PROC_MCA_LAST) {
X return -EBADF;
X }
X slot = type - PROC_MCA_SLOT;
X break;
X }
X
- /* if we made it here, we better have a valid slot */
+ /* If we made it here, we better have a valid slot */
X
- /* get the standard info */
+ /* Get the standard info */
X
- len = mca_default_procfn( page, slot );
+ len = mca_default_procfn(page, slot);
X
- /* do any device-specific processing, if there is any */
+ /* Do any device-specific processing, if there is any */
X
- if( mca_info->slot[slot].procfn ) {
- len += mca_info->slot[slot].procfn( page+len, slot,
- mca_info->slot[slot].dev );
+ if(mca_info->slot[slot].procfn) {
+ len += mca_info->slot[slot].procfn(page+len, slot,
+ mca_info->slot[slot].dev);
X }
X
X return len;
@@ -814,7 +821,7 @@
X
X #define PROC_BLOCK_SIZE (3*1024)
X
-static ssize_t proc_mca_read( struct file* file,
+static ssize_t proc_mca_read(struct file* file,
X char* buf, size_t count, loff_t *ppos)
X {
X unsigned long page;
@@ -825,11 +832,11 @@
X struct proc_dir_entry *dp;
X struct inode *inode = file->f_dentry->d_inode;
X
- if (count < 0)
+ if(count < 0)
X return -EINVAL;
- if (count > PROC_BLOCK_SIZE)
+ if(count > PROC_BLOCK_SIZE)
X count = PROC_BLOCK_SIZE;
- if (!(page = __get_free_page(GFP_KERNEL)))
+ if(!(page = __get_free_page(GFP_KERNEL)))
X return -ENOMEM;
X type = inode->i_ino;
X pid = type >> 16;
@@ -837,12 +844,12 @@
X start = 0;
X dp = (struct proc_dir_entry *) inode->u.generic_ip;
X length = mca_fill((char *) page, pid, type,
- &start, ppos, count);
- if (length < 0) {
+ &start, ppos, count);
+ if(length < 0) {
X free_page(page);
X return length;
X }
- if (start != 0) {
+ if(start != 0) {
X /* We have had block-adjusting processing! */
X
X copy_to_user(buf, start, length);
@@ -851,11 +858,11 @@
X } else {
X /* Static 4kB (or whatever) block capacity */
X
- if (*ppos >= length) {
+ if(*ppos >= length) {
X free_page(page);
X return 0;
X }
- if (count + *ppos > length)
+ if(count + *ppos > length)
X count = length - *ppos;
X end = count + *ppos;
X copy_to_user(buf, (char *) page + *ppos, count);
diff -u --recursive --new-file v2.2.5/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.5/linux/arch/i386/kernel/smp.c Tue Mar 23 14:35:46 1999
+++ linux/arch/i386/kernel/smp.c Mon Mar 29 11:14:50 1999
@@ -345,11 +345,13 @@
X SMP_PRINTK(("Bus #%d is %s\n",
X m->mpc_busid,
X str));
- if ((strncmp(m->mpc_bustype,"ISA",3) == 0) ||
- (strncmp(m->mpc_bustype,"EISA",4) == 0))
+ if (strncmp(m->mpc_bustype,"ISA",3) == 0)
X mp_bus_id_to_type[m->mpc_busid] =
X MP_BUS_ISA;
X else
+ if (strncmp(m->mpc_bustype,"EISA",4) == 0)
+ mp_bus_id_to_type[m->mpc_busid] =
+ MP_BUS_EISA;
X if (strncmp(m->mpc_bustype,"PCI",3) == 0) {
X mp_bus_id_to_type[m->mpc_busid] =
X MP_BUS_PCI;
diff -u --recursive --new-file v2.2.5/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.2.5/linux/arch/ppc/8xx_io/enet.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/8xx_io/enet.c Fri Apr 16 08:20:23 1999
@@ -21,6 +21,7 @@
X * small packets.
X *
X */
+#include <linux/config.h>
X #include <linux/kernel.h>
X #include <linux/sched.h>
X #include <linux/string.h>
diff -u --recursive --new-file v2.2.5/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.2.5/linux/arch/ppc/boot/head.S Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/boot/head.S Fri Apr 16 08:20:23 1999
@@ -1,4 +1,3 @@
-#include <linux/config.h>
X #include "../kernel/ppc_defs.h"
X #include "../kernel/ppc_asm.tmpl"
X #include <asm/processor.h>
diff -u --recursive --new-file v2.2.5/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- v2.2.5/linux/arch/ppc/lib/string.S Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/lib/string.S Fri Apr 16 08:20:23 1999
@@ -8,7 +8,6 @@
X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X */
-#include <linux/config.h>
X #include "../kernel/ppc_asm.tmpl"
X #include <asm/processor.h>
X #include <asm/errno.h>
diff -u --recursive --new-file v2.2.5/linux/arch/ppc/mbxboot/head.S linux/arch/ppc/mbxboot/head.S
--- v2.2.5/linux/arch/ppc/mbxboot/head.S Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/mbxboot/head.S Fri Apr 16 08:20:23 1999
@@ -1,4 +1,3 @@
-#include <linux/config.h>
X #include "../kernel/ppc_defs.h"
X #include "../kernel/ppc_asm.tmpl"
X #include <asm/processor.h>
diff -u --recursive --new-file v2.2.5/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.2.5/linux/drivers/block/Makefile Thu Sep 17 17:53:35 1998
+++ linux/drivers/block/Makefile Mon Apr 12 16:18:27 1999
@@ -220,6 +220,10 @@
X
X ifeq ($(CONFIG_BLK_DEV_PS2),y)
X L_OBJS += ps2esdi.o
+else
+ ifeq ($(CONFIG_BLK_DEV_PS2),m)
+ M_OBJS += ps2esdi.o
+ endif
X endif
X
X ifeq ($(CONFIG_BLK_DEV_XD),y)
diff -u --recursive --new-file v2.2.5/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.2.5/linux/drivers/block/genhd.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/block/genhd.c Mon Apr 12 16:18:27 1999
@@ -776,11 +776,14 @@
X #endif /* CONFIG_SUN_PARTITION */
X
X #ifdef CONFIG_SGI_PARTITION
+#include <asm/byteorder.h>
X
X static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
X {
X int i, csum;
X unsigned int *ui;
+ unsigned int start, blocks, cs;
+ int magic;
X struct buffer_head *bh;
X struct sgi_disklabel {
X int magic_mushroom; /* Big fat spliff... */
@@ -810,15 +813,18 @@
X }
X label = (struct sgi_disklabel *) bh->b_data;
X p = &label->partitions[0];
- if(label->magic_mushroom != SGI_LABEL_MAGIC) {
+ magic = label->magic_mushroom;
+ if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
X printk("Dev %s SGI disklabel: bad magic %08x\n",
- kdevname(dev), label->magic_mushroom);
+ kdevname(dev), magic);
X brelse(bh);
X return 0;
X }
X ui = ((unsigned int *) (label + 1)) - 1;
- for(csum = 0; ui >= ((unsigned int *) label);)
- csum += *ui--;
+ for(csum = 0; ui >= ((unsigned int *) label);) {
+ cs = *ui--;
+ csum += be32_to_cpu(cs);
+ }
X if(csum) {
X printk("Dev %s SGI disklabel: csum bad, label corrupted\n",
X kdevname(dev));
@@ -831,9 +837,11 @@
X * current_minor.
X */
X for(i = 0; i < 16; i++, p++) {
- if(!(p->num_blocks))
+ blocks = be32_to_cpu(p->num_blocks);
+ start = be32_to_cpu(p->first_block);
+ if(!blocks)
X continue;
- add_partition(hd, current_minor, p->first_block, p->num_blocks);
+ add_partition(hd, current_minor, start, blocks);
X current_minor++;
X }
X printk("\n");
diff -u --recursive --new-file v2.2.5/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.2.5/linux/drivers/block/ide-cd.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/block/ide-cd.c Mon Apr 12 16:18:26 1999
@@ -3005,9 +3005,6 @@
X CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
X else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
X CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
- else if (!strcmp (drive->id->model, "GCD-R580B"))
- CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
- /* 124/SECTORS_PER_FRAME; ? */
X }
X
X #if ! STANDARD_ATAPI
diff -u --recursive --new-file v2.2.5/linux/drivers/cdrom/Config.in linux/drivers/cdrom/Config.in
--- v2.2.5/linux/drivers/cdrom/Config.in Sun Dec 28 12:05:45 1997
+++ linux/drivers/cdrom/Config.in Mon Apr 12 16:18:28 1999
@@ -14,6 +14,10 @@
X fi
X fi
X tristate 'Mitsumi (standard) [no XA/Multisession] CDROM support' CONFIG_MCD
+if [ "$CONFIG_MCD" != "n" ]; then
+ int 'MCD IRQ' CONFIG_MCD_IRQ 11
+ hex 'MCD I/O base' CONFIG_MCD_BASE 300
+fi
X tristate 'Mitsumi [XA/MultiSession] CDROM support' CONFIG_MCDX
X tristate 'Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD
X tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206
diff -u --recursive --new-file v2.2.5/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.2.5/linux/drivers/cdrom/mcd.c Sun Nov 8 14:02:52 1998
+++ linux/drivers/cdrom/mcd.c Mon Apr 12 16:18:28 1999
@@ -67,6 +67,7 @@
X a CD.
X
X November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
+ March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
X */
X
X #include <linux/module.h>
@@ -83,6 +84,7 @@
X #include <linux/string.h>
X #include <linux/delay.h>
X #include <linux/init.h>
+#include <linux/config.h>
X
X /* #define REALLY_SLOW_IO */
X #include <asm/system.h>
@@ -155,8 +157,8 @@
X int mitsumi_bug_93_wait = 0;
X #endif /* WORK_AROUND_MITSUMI_BUG_93 */
X
-static short mcd_port = MCD_BASE_ADDR; /* used as "mcd" by "insmod" */
-static int mcd_irq = MCD_INTR_NR; /* must directly follow mcd_port */
+static short mcd_port = CONFIG_MCD_BASE; /* used as "mcd" by "insmod" */
+static int mcd_irq = CONFIG_MCD_IRQ; /* must directly follow mcd_port */
X MODULE_PARM(mcd, "1-2i");
X
X static int McdTimeout, McdTries;
diff -u --recursive --new-file v2.2.5/linux/drivers/cdrom/mcd.h linux/drivers/cdrom/mcd.h
--- v2.2.5/linux/drivers/cdrom/mcd.h Tue Dec 2 11:41:44 1997
+++ linux/drivers/cdrom/mcd.h Mon Apr 12 16:18:28 1999
@@ -21,20 +21,6 @@
X *
X */
X
-/* *** change this to set the I/O port address */
-#define MCD_BASE_ADDR 0x300
-
-/* *** change this to set the interrupt number */
-#define MCD_INTR_NR 11
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-
-/* #define I_WAS_HERE */
-
-
-
-
X /* Increase this if you get lots of timeouts */
X #define MCD_STATUS_DELAY 1000
X
@@ -121,8 +107,3 @@
X struct msf trackTime;
X struct msf diskTime;
X };
-
-#ifndef I_WAS_HERE
-#warning You have not edited mcd.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
diff -u --recursive --new-file v2.2.5/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.2.5/linux/drivers/cdrom/sjcd.c Tue Dec 22 14:16:55 1998
+++ linux/drivers/cdrom/sjcd.c Mon Apr 12 16:18:32 1999
@@ -45,11 +45,14 @@
X * Allow only to set io base address on command line: sjcd=<io_base>
X * Changes to Documentation/cdrom/sjcd
X * Added cleanup after any error in the initialisation.
+ * 1.7 Added code to set the sector size tables to prevent the bug present in
+ * the previous version of this driver. Coded added by Anthony Barbachan
+ * from bugfix tip originally suggested by Alan Cox.
X *
X */
X
X #define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 6
+#define SJCD_VERSION_MINOR 7
X
X #ifdef MODULE
X #include <linux/module.h>
@@ -1437,6 +1440,9 @@
X NULL /* revalidate */
X };
X
+static int blksize = 2048;
+static int secsize = 2048;
+
X /*
X * Following stuff is intended for initialization of the cdrom. It
X * first looks for presence of device. If the device is present, it
@@ -1460,6 +1466,9 @@
X #if defined( SJCD_TRACE )
X printk("SJCD: sjcd=0x%x: ", sjcd_base);
X #endif
+
+ hardsect_size[MAJOR_NR] = &secsize;
+ blksize_size[MAJOR_NR] = &blksize;
X
X if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){
X printk( "SJCD: Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
diff -u --recursive --new-file v2.2.5/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.2.5/linux/drivers/char/Config.in Mon Mar 29 11:09:11 1999
+++ linux/drivers/char/Config.in Thu Apr 15 05:42:40 1999
@@ -123,6 +123,7 @@
X if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
X hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
X fi
+ dep_tristate 'ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
X dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
X dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
X if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
diff -u --recursive --new-file v2.2.5/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.2.5/linux/drivers/char/Makefile Mon Mar 29 11:09:11 1999
+++ linux/drivers/char/Makefile Thu Apr 15 05:42:40 1999
@@ -401,6 +401,14 @@
X endif
X endif
X
+ifeq ($(CONFIG_RADIO_CADET),y)
+L_OBJS += radio-cadet.o
+else
+ ifeq ($(CONFIG_RADIO_CADET),m)
+ M_OBJS += radio-cadet.o
+ endif
+endif
+
X ifeq ($(CONFIG_RADIO_MIROPCM20),y)
X L_OBJS += radio-miropcm20.o
X else
@@ -459,6 +467,7 @@
X ALL_SUB_DIRS += hfmodem
X MOD_SUB_DIRS += hfmodem
X endif
+
X endif
X
X include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.2.5/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.2.5/linux/drivers/char/bttv.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/char/bttv.c Mon Apr 12 16:18:27 1999
@@ -541,6 +541,8 @@
X { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
X /* Zoltrix TV-Max */
X { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
+ /* Pixelview PlayTV (bt878) */
+ { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},
X };
X #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
X
@@ -2388,7 +2390,7 @@
X
X btv->user--;
X btv->radio = 0;
- audio(btv, AUDIO_MUTE);
+ /*audio(btv, AUDIO_MUTE);*/
X MOD_DEC_USE_COUNT;
X }
X
@@ -2927,6 +2929,12 @@
X btv->pll.pll_crystal=BT848_IFORM_XT0;
X }
X }
+
+ if (btv->type == BTTV_PIXVIEWPLAYTV) {
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ }
+
X if(btv->type==BTTV_AVERMEDIA98)
X {
X btv->pll.pll_ifreq=28636363;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.2.5/linux/drivers/char/bttv.h Tue Feb 23 15:21:33 1999
+++ linux/drivers/char/bttv.h Mon Apr 12 16:18:27 1999
@@ -208,6 +208,7 @@
X #define BTTV_AVERMEDIA98 0x0d
X #define BTTV_VHX 0x0e
X #define BTTV_ZOLTRIX 0x0f
+#define BTTV_PIXVIEWPLAYTV 0x10
X
X #define AUDIO_TUNER 0x00
X #define AUDIO_RADIO 0x01
diff -u --recursive --new-file v2.2.5/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.2.5/linux/drivers/char/cyclades.c Wed Jan 20 23:14:05 1999
+++ linux/drivers/char/cyclades.c Mon Apr 12 10:09:47 1999
@@ -1,7 +1,7 @@
X #define BLOCKMOVE
X #define Z_WAKE
X static char rcsid[] =
-"$Revision: 2.2.1.10 $$Date: 1999/01/20 16:14:29 $";
+"$Revision: 2.2.2.1 $$Date: 1999/04/08 16:17:43 $";
X
X /*
X * linux/drivers/char/cyclades.c
@@ -31,6 +31,13 @@
X * void cleanup_module(void);
X *
X * $Log: cyclades.c,v $
+ * Revision 2.2.2.1 1999/04/08 16:17:43 ivan
+ * Fixed a bug in cy_wait_until_sent that was preventing the port to be
+ * closed properly after a SIGINT;
+ * Module usage counter scheme revisited;
+ * Added support to the upcoming Y PCI boards (i.e., support to additional
+ * PCI Device ID's).
+ *
X * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
X * Removed all unnecessary page-alignement operations in ioremap calls
X * (ioremap is currently safe for these operations).
@@ -525,9 +532,11 @@
X #undef CY_DEBUG_COUNT
X #undef CY_DEBUG_DTR
X #undef CY_DEBUG_WAIT_UNTIL_SENT
+#undef CY_DEBUG_INTERRUPTS
X #undef CY_16Y_HACK
X #undef CY_ENABLE_MONITORING
X #undef CY_PCI_DEBUG
+#define CY_PROC
X
X #if 0
X #define PAUSE __asm__("nop");
@@ -763,16 +772,20 @@
X
X /* PCI related definitions */
X
-static unsigned short cy_pci_nboard = 0;
-static unsigned short cy_isa_nboard = 0;
-static unsigned short cy_nboard = 0;
-static unsigned short cy_pci_dev_id[] = {
- PCI_DEVICE_ID_CYCLOM_Y_Lo,/* PCI below 1Mb */
- PCI_DEVICE_ID_CYCLOM_Y_Hi,/* PCI above 1Mb */
- PCI_DEVICE_ID_CYCLOM_Z_Lo,/* PCI below 1Mb */
- PCI_DEVICE_ID_CYCLOM_Z_Hi,/* PCI above 1Mb */
- 0 /* end of table */
- };
+static unsigned short cy_pci_nboard = 0;
+static unsigned short cy_isa_nboard = 0;
+static unsigned short cy_nboard = 0;
+static unsigned short cy_pci_dev_id[] = {
+ PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */
+ 0 /* end of table */
+ };
X
X
X static void cy_start(struct tty_struct *);
@@ -2448,12 +2461,15 @@
X int retval, line;
X unsigned long page;
X
+ MOD_INC_USE_COUNT;
X line = MINOR(tty->device) - tty->driver.minor_start;
X if ((line < 0) || (NR_PORTS <= line)){
+ MOD_DEC_USE_COUNT;
X return -ENODEV;
X }
X info = &cy_port[line];
X if (info->line < 0){
+ MOD_DEC_USE_COUNT;
X return -ENODEV;
X }
X
@@ -2479,6 +2495,8 @@
X #ifdef CY_DEBUG_OTHER
X printk("cyc:cy_open ttyC%d\n", info->line); /* */
X #endif
+ tty->driver_data = info;
+ info->tty = tty;
X if (serial_paranoia_check(info, tty->device, "cy_open")){
X return -ENODEV;
X }
@@ -2491,9 +2509,6 @@
X printk("cyc:cy_open (%d): incrementing count to %d\n",
X current->pid, info->count);
X #endif
- tty->driver_data = info;
- info->tty = tty;
-
X if (!tmp_buf) {
X page = get_free_page(GFP_KERNEL);
X if (!page)
@@ -2521,8 +2536,6 @@
X return retval;
X }
X
- MOD_INC_USE_COUNT;
-
X retval = block_til_ready(tty, filp, info);
X if (retval) {
X #ifdef CY_DEBUG_OPEN
@@ -2563,6 +2576,10 @@
X if (serial_paranoia_check(info, tty->device, "cy_wait_until_sent"))
X return;
X
+ if (info->xmit_fifo_size == 0)
+ return; /* Just in case.... */
+
+
X orig_jiffies = jiffies;
X /*
X * Set the check interval to be 1/5 of the estimated time to
@@ -2580,6 +2597,17 @@
X timeout = 0;
X if (timeout)
X char_time = MIN(char_time, timeout);
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than info->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*info->timeout.
+ */
+ if (!timeout || timeout > 2*info->timeout)
+ timeout = 2*info->timeout;
X #ifdef CY_DEBUG_WAIT_UNTIL_SENT
X printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
X printk("jiff=%lu...", jiffies);
@@ -2601,7 +2629,7 @@
X schedule_timeout(char_time);
X if (signal_pending(current))
X break;
- if (timeout && time_before(orig_jiffies + timeout, jiffies))
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
X break;
X }
X current->state = TASK_RUNNING;
@@ -2631,13 +2659,9 @@
X printk("cyc:cy_close ttyC%d\n", info->line);
X #endif
X
- if (!info
- || serial_paranoia_check(info, tty->device, "cy_close")){
+ if (!info || serial_paranoia_check(info, tty->device, "cy_close")){
X return;
X }
-#ifdef CY_DEBUG_OPEN
- printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
-#endif
X
X save_flags(flags); cli();
X
@@ -2648,6 +2672,9 @@
X return;
X }
X
+#ifdef CY_DEBUG_OPEN
+ printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
+#endif
X if ((tty->count == 1) && (info->count != 1)) {
X /*
X * Uh, oh. tty->count is 1, which means that the tty
@@ -4579,6 +4606,8 @@
X cy_pci_addr2 = pdev->base_address[2];
X pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
X
+ device_id &= ~PCI_DEVICE_ID_MASK;
+
X if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
X || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
X #ifdef CY_PCI_DEBUG
@@ -4942,6 +4971,7 @@
X __DATE__, __TIME__);
X } /* show_version */
X
+#ifdef CY_PROC
X static int
X cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
X int *eof, void *data)
@@ -4998,7 +5028,7 @@
X len = 0;
X return len;
X }
-
+#endif
X
X /* The serial driver boot-time initialization code!
X Hardware I/O ports are mapped to character special devices on a
@@ -5028,7 +5058,9 @@
X unsigned long mailbox;
X unsigned short chip_number;
X int nports;
+#ifdef CY_PROC
X struct proc_dir_entry *ent;
+#endif
X
X show_version();
X
@@ -5269,8 +5301,10 @@
X #endif
X }
X
+#ifdef CY_PROC
X ent = create_proc_entry("cyclades", S_IFREG | S_IRUGO, 0);
X ent->read_proc = cyclades_get_proc_info;
+#endif
X
X return 0;
X
@@ -5314,7 +5348,7 @@
X free_irq(cy_card[i].irq,NULL);
X }
X }
-#ifdef CONFIG_PROC_FS
+#ifdef CY_PROC
X remove_proc_entry("cyclades", 0);
X #endif
X
diff -u --recursive --new-file v2.2.5/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.2.5/linux/drivers/char/dtlk.c Wed Mar 10 15:29:45 1999
+++ linux/drivers/char/dtlk.c Fri Apr 16 08:20:23 1999
@@ -56,8 +56,6 @@
X #endif
X
X #define KERNEL
-#include <linux/config.h>
-
X #include <linux/types.h>
X #include <linux/fs.h>
X #include <linux/mm.h> /* for verify_area */
diff -u --recursive --new-file v2.2.5/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.2.5/linux/drivers/char/isicom.c Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/isicom.c Mon Apr 12 16:18:27 1999
@@ -114,6 +114,7 @@
X #ifdef ISICOM_DEBUG
X printk(KERN_DEBUG "ISILoad:Firmware loader Opened!!!\n");
X #endif
+ MOD_INC_USE_COUNT;
X return 0;
X }
X
@@ -122,6 +123,7 @@
X #ifdef ISICOM_DEBUG
X printk(KERN_DEBUG "ISILoad:Firmware loader Close(Release)d\n",);
X #endif
+ MOD_DEC_USE_COUNT;
X return 0;
X }
X
diff -u --recursive --new-file v2.2.5/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.2.5/linux/drivers/char/istallion.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/char/istallion.c Fri Apr 16 08:20:23 1999
@@ -26,6 +26,7 @@
X
X /*****************************************************************************/
X
+#include <linux/config.h>
X #include <linux/module.h>
X #include <linux/malloc.h>
X #include <linux/interrupt.h>
diff -u --recursive --new-file v2.2.5/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.2.5/linux/drivers/char/mem.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/char/mem.c Mon Apr 12 10:35:41 1999
@@ -138,8 +138,11 @@
X static inline unsigned long pgprot_noncached(unsigned long prot)
X {
X #if defined(__i386__)
+ /* On PPro and successors, PCD alone doesn't always mean
+ uncached because of interactions with the MTRRs. PCD | PWT
+ means definitely uncached. */
X if (boot_cpu_data.x86 > 3)
- prot |= _PAGE_PCD;
+ prot |= _PAGE_PCD | _PAGE_PWT;
X #elif defined(__powerpc__)
X prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
X #elif defined(__mc68000__)
@@ -155,6 +158,28 @@
X return prot;
X }
X
+/*
+ * Architectures vary in how they handle caching for addresses
+ * outside of main memory.
+ */
+static inline int noncached_address(unsigned long addr)
+{
+#if defined(__i386__)
+ /*
+ * On the PPro and successors, the MTRRs are used to set
+ * memory types for physical addresses outside main memory,
+ * so blindly setting PCD or PWT on those pages is wrong.
+ * For Pentiums and earlier, the surround logic should disable
+ * caching for the high addresses through the KEN pin, but
+ * we maintain the tradition of paranoia in this code.
+ */
+ return !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR)
+ && addr >= __pa(high_memory);
+#else
+ return addr >= __pa(high_memory);
+#endif
+}
+
X static int mmap_mem(struct file * file, struct vm_area_struct * vma)
X {
X unsigned long offset = vma->vm_offset;
@@ -166,15 +191,17 @@
X * Accessing memory above the top the kernel knows about or
X * through a file pointer that was marked O_SYNC will be
X * done non-cached.
- *
- * Set VM_IO, as this is likely a non-cached access to an
- * I/O area, and we don't want to include that in a core
- * file.
X */
- if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC)) {
- pgprot_val(vma->vm_page_prot) = pgprot_noncached(pgprot_val(vma->vm_page_prot));
+ if (noncached_address(offset) || (file->f_flags & O_SYNC))
+ pgprot_val(vma->vm_page_prot)
+ = pgprot_noncached(pgprot_val(vma->vm_page_prot));
+
+ /*
+ * Don't dump addresses that are not real memory to a core file.
+ */
+ if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
X vma->vm_flags |= VM_IO;
- }
+
X if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
X vma->vm_page_prot))
X return -EAGAIN;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c
--- v2.2.5/linux/drivers/char/radio-aimslab.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/char/radio-aimslab.c Thu Apr 15 05:42:40 1999
@@ -235,6 +235,7 @@
X v.rangehigh=(108*16000);
X v.flags=VIDEO_TUNER_LOW;
X v.mode=VIDEO_MODE_AUTO;
+ strcpy(v.name, "FM");
X v.signal=0xFFFF*rt_getsigstr(rt);
X if(copy_to_user(arg,&v, sizeof(v)))
X return -EFAULT;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-aztech.c linux/drivers/char/radio-aztech.c
--- v2.2.5/linux/drivers/char/radio-aztech.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/char/radio-aztech.c Thu Apr 15 05:42:40 1999
@@ -186,6 +186,7 @@
X v.signal=0xFFFF*az_getsigstr(az);
X if(az_getstereo(az))
X v.flags|=VIDEO_TUNER_STEREO_ON;
+ strcpy(v.name, "FM");
X if(copy_to_user(arg,&v, sizeof(v)))
X return -EFAULT;
X return 0;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- v2.2.5/linux/drivers/char/radio-cadet.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/radio-cadet.c Thu Apr 15 05:42:40 1999
@@ -0,0 +1,403 @@
+/* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
+ *
+ * by Fred Gleason <fr...@wava.com>
+ * Version 0.1.2
+ *
+ * (Loosely) based on code for the Aztech radio card by
+ *
+ * Russell Kroll (rkr...@exploits.org)
+ * Quay Ly
+ * Donald Song
+ * Jason Lewis (jle...@twilight.vtc.vsc.edu)
+ * Scott McGrath (smcg...@twilight.vtc.vsc.edu)
+ * William McGrath (wmcg...@twilight.vtc.vsc.edu)
+ *
+*/
+
+#include <linux/module.h> /* Modules */
+#include <linux/init.h> /* Initdata */
+#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/delay.h> /* udelay */
+#include <asm/io.h> /* outb, outb_p */
+#include <asm/uaccess.h> /* copy to/from user */
+#include <linux/videodev.h> /* kernel radio structs */
+#include <linux/config.h> /* CONFIG_RADIO_CADET_PORT */
+
+#ifndef CONFIG_RADIO_CADET_PORT
+#define CONFIG_RADIO_CADET_PORT 0x330
+#endif
+
+static int io=CONFIG_RADIO_CADET_PORT;
+static int users=0;
+static int curtuner=0;
+
+static int cadet_getstereo(void)
+{
+ if(curtuner!=0) { /* Only FM has stereo capability! */
+ return 0;
+ }
+ outb(7,io); /* Select tuner control */
+ if((inb(io+1)&0x40)==0) {
+ return 1; /* Stereo pilot detected */
+ }
+ else {
+ return 0; /* Mono */
+ }
+}
+
+
+static unsigned cadet_getfreq(void)
+{
+ int curvol,i;
+ unsigned freq=0,test,fifo=0;
+
+
+ /*
+ * Prepare for read
+ */
+ outb(7,io); /* Select tuner control */
+ curvol=inb(io+1); /* Save current volume/mute setting */
+ outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */
+
+ /*
+ * Read the shift register
+ */
+ for(i=0;i<25;i++) {
+ fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
+ if(i<24) {
+ outb(0x01,io+1);
+ outb(0x00,io+1);


+ }
+ }
+
+ /*

+ * Restore volume/mute setting
+ */
+ outb(curvol,io+1);
+
+ /*
+ * Convert to actual frequency
+ */
+ if(curtuner==0) { /* FM */
+ test=12500;
+ for(i=0;i<14;i++) {
+ if((fifo&0x01)!=0) {
+ freq+=test;
+ }
+ test=test<<1;
+ fifo=fifo>>1;
+ }
+ freq-=10700000; /* IF frequency is 10.7 MHz */
+ freq=(freq*16)/1000000; /* Make it 1/16 MHz */
+ }
+ if(curtuner==1) { /* AM */
+ freq=((fifo&0x7fff)-2010)*16;
+ }
+
+ return freq;
+}
+
+
+static void cadet_setfreq(unsigned freq)
+{
+ unsigned fifo;
+ int i,test;
+ int curvol;
+
+ /*
+ * Formulate a fifo command
+ */
+ fifo=0;
+ if(curtuner==0) { /* FM */
+ test=102400;
+ freq=(freq*1000)/16; /* Make it kHz */
+ freq+=10700; /* IF is 10700 kHz */
+ for(i=0;i<14;i++) {
+ fifo=fifo<<1;
+ if(freq>=test) {
+ fifo|=0x01;
+ freq-=test;
+ }
+ test=test>>1;
+ }
+ }
+ if(curtuner==1) { /* AM */
+ fifo=(freq/16)+2010; /* Make it kHz */
+ fifo|=0x100000; /* Select AM Band */
+ }
+
+ /*
+ * Save current volume/mute setting
+ */
+ curvol=inb(io+1);
+
+ /*
+ * Write the shift register
+ */
+ test=0;
+ test=(fifo>>23)&0x02; /* Align data for SDO */
+ test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */
+ outb(7,io); /* Select tuner control */
+ outb(test,io+1); /* Initialize for write */
+ for(i=0;i<25;i++) {
+ test|=0x01; /* Toggle SCK High */
+ outb(test,io+1);
+ test&=0xfe; /* Toggle SCK Low */
+ outb(test,io+1);
+ fifo=fifo<<1; /* Prepare the next bit */
+ test=0x1c|((fifo>>23)&0x02);
+ outb(test,io+1);
+ }
+ /*
+ * Restore volume/mute setting
+ */
+ outb(curvol,io+1);
+}
+
+
+static int cadet_getvol(void)
+{
+ outb(7,io); /* Select tuner control */
+ if((inb(io+1)&0x20)!=0) {
+ return 0xffff;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+static void cadet_setvol(int vol)
+{
+ outb(7,io); /* Select tuner control */
+ if(vol>0) {
+ outb(0x20,io+1);
+ }
+ else {
+ outb(0x00,io+1);
+ }
+}
+
+
+static int cadet_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ unsigned freq;
+ switch(cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+ v.type=VID_TYPE_TUNER;
+ v.channels=2;
+ v.audios=1;
+ /* No we don't do pictures */
+ v.maxwidth=0;
+ v.maxheight=0;
+ v.minwidth=0;
+ v.minheight=0;
+ strcpy(v.name, "ADS Cadet");
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg,sizeof(v))!=0) {
+ return -EFAULT;
+ }
+ if((v.tuner<0)||(v.tuner>1)) {
+ return -EINVAL;
+ }
+ switch(v.tuner) {
+ case 0:
+ strcpy(v.name,"FM");
+ v.rangelow=1400; /* 87.5 MHz */
+ v.rangehigh=1728; /* 108.0 MHz */
+ v.flags=0;
+ v.mode=0;
+ v.mode|=VIDEO_MODE_AUTO;
+ v.signal=0xFFFF;
+ if(cadet_getstereo()==1) {
+ v.flags|=VIDEO_TUNER_STEREO_ON;
+ }
+ if(copy_to_user(arg,&v, sizeof(v))) {
+ return -EFAULT;
+ }
+ break;
+ case 1:
+ strcpy(v.name,"AM");
+ v.rangelow=8320; /* 520 kHz */
+ v.rangehigh=26400; /* 1650 kHz */
+ v.flags=0;
+ v.flags|=VIDEO_TUNER_LOW;
+ v.mode=0;
+ v.mode|=VIDEO_MODE_AUTO;
+ v.signal=0xFFFF;
+ if(copy_to_user(arg,&v, sizeof(v))) {
+ return -EFAULT;
+ }
+ break;
+ }
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg, sizeof(v))) {
+ return -EFAULT;
+ }
+ if((v.tuner<0)||(v.tuner>1)) {
+ return -EINVAL;
+ }
+ curtuner=v.tuner;
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ freq=cadet_getfreq();
+ if(copy_to_user(arg, &freq, sizeof(freq)))
+ return -EFAULT;
+ return 0;
+ case VIDIOCSFREQ:
+ if(copy_from_user(&freq, arg,sizeof(freq)))
+ return -EFAULT;
+ if((curtuner==0)&&((freq<1400)||(freq>1728))) {
+ return -EINVAL;
+ }
+ if((curtuner==1)&&((freq<8320)||(freq>26400))) {
+ return -EINVAL;
+ }
+ cadet_setfreq(freq);
+ return 0;
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+ memset(&v,0, sizeof(v));
+ v.flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
+ if(cadet_getstereo()==0) {
+ v.mode=VIDEO_SOUND_MONO;
+ }
+ else {
+ v.mode=VIDEO_SOUND_STEREO;
+ }
+ v.volume=cadet_getvol();
+ v.step=0xffff;
+ strcpy(v.name, "Radio");
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.audio)
+ return -EINVAL;
+ cadet_setvol(v.volume);
+ if(v.flags&VIDEO_AUDIO_MUTE)
+ cadet_setvol(0);
+ else
+ cadet_setvol(0xffff);
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+
+static int cadet_open(struct video_device *dev, int flags)
+{
+ if(users)
+ return -EBUSY;
+ users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void cadet_close(struct video_device *dev)
+{
+ users--;
+ MOD_DEC_USE_COUNT;
+}
+
+
+static struct video_device cadet_radio=
+{
+ "Cadet radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_CADET,
+ cadet_open,
+ cadet_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ NULL, /* No poll */
+ cadet_ioctl,
+ NULL,
+ NULL
+};
+
+__initfunc(int cadet_init(struct video_init *v))
+{
+#ifndef MODULE
+ if(cadet_probe()<0) {
+ return EINVAL;
+ }
+#endif
+ if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io,2,"cadet");
+ printk(KERN_INFO "ADS Cadet Radio Card at %x\n",io);
+ return 0;
+}
+
+
+static int cadet_probe(void)
+{
+ static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
+ int i;
+
+ for(i=0;i<8;i++) {
+ io=iovals[i];
+ if(check_region(io,2)) {
+ return -1;
+ }
+ cadet_setfreq(1410);
+ if(cadet_getfreq()==1410) {
+ return io;
+ }
+ }
+ return -1;
+}
+
+
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
+MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+ return -EINVAL;
+ }
+ return cadet_init(NULL);
+}
+
+void cleanup_module(void)
+{
+ video_unregister_device(&cadet_radio);
+ release_region(io,2);
+}
+
+#endif
+
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-gemtek.c linux/drivers/char/radio-gemtek.c
--- v2.2.5/linux/drivers/char/radio-gemtek.c Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/radio-gemtek.c Thu Apr 15 05:42:40 1999
@@ -160,6 +160,7 @@
X v.flags=VIDEO_TUNER_LOW;
X v.mode=VIDEO_MODE_AUTO;
X v.signal=0xFFFF*gemtek_getsigstr(rt);
+ strcpy(v.name, "FM");
X if(copy_to_user(arg,&v, sizeof(v)))
X return -EFAULT;
X return 0;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-miropcm20.c linux/drivers/char/radio-miropcm20.c
--- v2.2.5/linux/drivers/char/radio-miropcm20.c Sat Sep 5 16:46:40 1998
+++ linux/drivers/char/radio-miropcm20.c Thu Apr 15 05:42:40 1999
@@ -118,6 +118,7 @@
X v.flags=0;
X v.mode=VIDEO_MODE_AUTO;
X v.signal=0xFFFF*pcm20_getsigstr(pcm20);
+ strcpy(v.name, "FM");
X if(copy_to_user(arg,&v, sizeof(v)))
X return -EFAULT;
X return 0;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-rtrack2.c linux/drivers/char/radio-rtrack2.c
--- v2.2.5/linux/drivers/char/radio-rtrack2.c Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/radio-rtrack2.c Thu Apr 15 05:42:40 1999
@@ -130,6 +130,7 @@
X v.flags=VIDEO_TUNER_LOW;
X v.mode=VIDEO_MODE_AUTO;
X v.signal=0xFFFF*rt_getsigstr(rt);
+ strcpy(v.name, "FM");
X if(copy_to_user(arg,&v, sizeof(v)))
X return -EFAULT;
X return 0;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c
--- v2.2.5/linux/drivers/char/radio-sf16fmi.c Fri Nov 27 13:09:23 1998
+++ linux/drivers/char/radio-sf16fmi.c Thu Apr 15 05:42:40 1999
@@ -158,6 +158,7 @@
X v.flags=fmi->flags;
X v.mode=VIDEO_MODE_AUTO;
X v.signal = fmi_getsigstr(fmi);
+ strcpy(v.name, "FM");
X if(copy_to_user(arg,&v, sizeof(v)))
X return -EFAULT;
X return 0;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-typhoon.c linux/drivers/char/radio-typhoon.c
--- v2.2.5/linux/drivers/char/radio-typhoon.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/char/radio-typhoon.c Thu Apr 15 05:42:40 1999
@@ -195,7 +195,8 @@
X v.rangehigh = 1080 * 1600;
X v.flags = VIDEO_TUNER_LOW;
X v.mode = VIDEO_MODE_AUTO;
- v.signal = 0; /* We can't get the signal strength */
+ v.signal = 0xFFFF; /* We can't get the signal strength */
+ strcpy(v.tuner, "FM");
X if (copy_to_user(arg, &v, sizeof(v)))
X return -EFAULT;
X return 0;
diff -u --recursive --new-file v2.2.5/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.2.5/linux/drivers/char/radio-zoltrix.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/char/radio-zoltrix.c Thu Apr 15 05:42:40 1999
@@ -223,14 +223,11 @@
X case VIDIOCGTUNER:
X {
X struct video_tuner v;
-/*
X if (copy_from_user(&v, arg, sizeof(v)))
X return -EFAULT;
X if (v.tuner)
X return -EINVAL;
-*/
- v.tuner = 0;
- strcpy(v.name, "Zoltrix Radio");
+ strcpy(v.name, "FM");
X v.rangelow = (int) (88.0 * 16000);
X v.rangehigh = (int) (108.0 * 16000);
X v.flags = zol_is_stereo(zol)
diff -u --recursive --new-file v2.2.5/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.2.5/linux/drivers/char/softdog.c Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/softdog.c Mon Apr 12 16:18:27 1999
@@ -144,11 +144,9 @@
X default:
X return -ENOIOCTLCMD;
X case WDIOC_GETSUPPORT:
- i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info));
- if (i)
- return i;
- else
- return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
+ if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+ return -EFAULT;
+ return 0;
X case WDIOC_GETSTATUS:
X case WDIOC_GETBOOTSTATUS:
X return put_user(0,(int *)arg);
diff -u --recursive --new-file v2.2.5/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.2.5/linux/drivers/char/stallion.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/char/stallion.c Fri Apr 16 08:20:23 1999
@@ -26,6 +26,7 @@
X
X /*****************************************************************************/
X
+#include <linux/config.h>
X #include <linux/module.h>
X #include <linux/malloc.h>
X #include <linux/interrupt.h>
diff -u --recursive --new-file v2.2.5/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.2.5/linux/drivers/char/videodev.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/char/videodev.c Thu Apr 15 05:42:40 1999
@@ -75,6 +75,9 @@
X #ifdef CONFIG_RADIO_TYPHOON
X extern int typhoon_init(struct video_init *);
X #endif
+#ifdef CONFIG_RADIO_CADET
+extern int cadet_init(struct video_init *);
+#endif
X #ifdef CONFIG_VIDEO_PMS
X extern int init_pms_cards(struct video_init *);
X #endif
@@ -111,6 +114,9 @@
X #ifdef CONFIG_RADIO_MIROPCM20
X {"PCM20", pcm20_init},
X #endif
+#ifdef CONFIG_RADIO_CADET
+ {"Cadet", cadet_init},
+#endif
X #ifdef CONFIG_RADIO_GEMTEK
X {"GemTek", gemtek_init},
X #endif
@@ -429,6 +435,12 @@
X {
X unregister_chrdev(VIDEO_MAJOR, "video_capture");
X }
+
+
+
+
+
+
X
X #endif
X
diff -u --recursive --new-file v2.2.5/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.2.5/linux/drivers/macintosh/adb.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/macintosh/adb.c Fri Apr 16 08:20:23 1999
@@ -5,7 +5,6 @@
X * Copyright (C) 1996 Paul Mackerras.
X */
X
-#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/errno.h>
X #include <linux/kernel.h>
diff -u --recursive --new-file v2.2.5/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.2.5/linux/drivers/net/Makefile Tue Mar 23 14:35:47 1999
+++ linux/drivers/net/Makefile Thu Apr 15 05:42:40 1999
@@ -1073,7 +1073,7 @@
X MOD_IN_SUB_DIRS += irda
X else
X ifeq ($(CONFIG_IRDA),m)
- MOD_SUB_DIRS += irda
+ MOD_IN_SUB_DIRS += irda
X endif
X endif
X
diff -u --recursive --new-file v2.2.5/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.2.5/linux/drivers/net/defxx.c Tue Feb 23 15:21:33 1999
+++ linux/drivers/net/defxx.c Fri Apr 16 13:58:46 1999
@@ -1911,6 +1911,8 @@
X }
X bp = (DFX_board_t *) dev->priv;
X
+ spin_lock(&bp->lock);
+
X /* See if we're already servicing an interrupt */
X
X if (dev->interrupt)
@@ -1955,6 +1957,7 @@
X }
X
X dev->interrupt = DFX_UNMASK_INTERRUPTS;
+ spin_unlock(&bp->lock);
X return;
X }
X
@@ -3205,10 +3208,11 @@
X )
X
X {
- DFX_board_t *bp = (DFX_board_t *) dev->priv;
- u8 prod; /* local transmit producer index */
+ DFX_board_t *bp = (DFX_board_t *) dev->priv;
+ u8 prod; /* local transmit producer index */
X PI_XMT_DESCR *p_xmt_descr; /* ptr to transmit descriptor block entry */
X XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */
+ unsigned long flags;
X
X /*
X * Verify that incoming transmit request is OK
@@ -3252,6 +3256,8 @@
X }
X }
X
+ spin_lock_irqsave(&bp->lock, flags);
+
X /* Get the current producer and the next free xmt data descriptor */
X
X prod = bp->rcv_xmt_reg.index.xmt_prod;
@@ -3272,9 +3278,10 @@
X
X /* Write the three PRH bytes immediately before the FC byte */
X
- *((char *)skb->data - 3) = DFX_PRH0_BYTE; /* these byte values are defined */
- *((char *)skb->data - 2) = DFX_PRH1_BYTE; /* in the Motorola FDDI MAC chip */
- *((char *)skb->data - 1) = DFX_PRH2_BYTE; /* specification */
+ skb_push(skb,3);
+ skb->data[0] = DFX_PRH0_BYTE; /* these byte values are defined */
+ skb->data[1] = DFX_PRH1_BYTE; /* in the Motorola FDDI MAC chip */
+ skb->data[2] = DFX_PRH2_BYTE; /* specification */
X
X /*
X * Write the descriptor with buffer info and bump producer
@@ -3304,7 +3311,7 @@
X */
X
X p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len + 3) << PI_XMT_DESCR_V_SEG_LEN));
- p_xmt_descr->long_1 = (u32) virt_to_bus(skb->data - 3);
+ p_xmt_descr->long_1 = (u32) virt_to_bus(skb->data);
X
X /*
X * Verify that descriptor is actually available
@@ -3318,7 +3325,11 @@
X */
X
X if (prod == bp->rcv_xmt_reg.index.xmt_comp)
+ {
+ skb_pull(skb,3);
+ spin_unlock_irqrestore(&bp->lock, flags);
X return(1); /* requeue packet for later */
+ }
X
X /*
X * Save info for this packet for xmt done indication routine
@@ -3342,6 +3353,7 @@
X
X bp->rcv_xmt_reg.index.xmt_prod = prod;
X dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+ spin_unlock_irqrestore(&bp->lock, flags);
X return(0); /* packet queued to adapter */
X }
X
diff -u --recursive --new-file v2.2.5/linux/drivers/net/defxx.h linux/drivers/net/defxx.h
--- v2.2.5/linux/drivers/net/defxx.h Fri May 8 23:14:48 1998
+++ linux/drivers/net/defxx.h Fri Apr 16 13:58:46 1999
@@ -1748,6 +1748,10 @@
X /* Store pointers to transmit buffers for transmit completion code */
X
X XMT_DRIVER_DESCR xmt_drv_descr_blk[PI_XMT_DATA_K_NUM_ENTRIES];
+
+ /* Transmit spinlocks */
+
+ spinlock_t lock;
X
X /* Store device, bus-specific, and parameter information for this adapter */
X
diff -u --recursive --new-file v2.2.5/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.2.5/linux/drivers/net/irda/Makefile Wed Mar 10 15:29:46 1999
+++ linux/drivers/net/irda/Makefile Thu Apr 15 05:42:41 1999
@@ -10,7 +10,7 @@
X L_TARGET := irda_drivers.a
X L_OBJS :=
X M_OBJS :=
-MOD_LIST_NAME := IRDA_MODULES
+MOD_LIST_NAME := IRDA_DRIVERS_MODULES
X
X ifeq ($(CONFIG_IRTTY_SIR),y)
X L_OBJS += irtty.o
diff -u --recursive --new-file v2.2.5/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.2.5/linux/drivers/net/irda/irport.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/net/irda/irport.c Thu Apr 15 05:42:41 1999
@@ -64,13 +64,14 @@
X #include <net/irda/irport.h>
X
X #define IO_EXTENT 8
+#define CONFIG_HALF_DUPLEX
X
-static unsigned int io[] = { 0x3e8, ~0, ~0, ~0 };
-static unsigned int irq[] = { 11, 0, 0, 0 };
+/* static unsigned int io[] = { 0x3e8, ~0, ~0, ~0 }; */
+/* static unsigned int irq[] = { 11, 0, 0, 0 }; */
X
-static void irport_write_wakeup( struct irda_device *idev);
-static int irport_write( int iobase, int fifo_size, __u8 *buf, int len);
-static void irport_receive( struct irda_device *idev);
+static void irport_write_wakeup(struct irda_device *idev);
+static int irport_write(int iobase, int fifo_size, __u8 *buf, int len);
+static void irport_receive(struct irda_device *idev);
X
X __initfunc(int irport_init(void))
X {
@@ -115,15 +116,15 @@
X */
X int irport_open( int iobase)
X {
- DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+ DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
X
X /* Initialize UART */
- outb( UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
- outb(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
+ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
+ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
X
X /* Turn on interrups */
- outb(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER);
-
+ outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER);
+
X return 0;
X }
X
@@ -135,13 +136,13 @@
X */
X void irport_close( int iobase)
X {
- DEBUG( 0, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
X
X /* Reset UART */
- outb( 0, iobase+UART_MCR);
+ outb(0, iobase+UART_MCR);
X
X /* Turn off interrupts */
- outb( 0, iobase+UART_IER);
+ outb(0, iobase+UART_IER);
X }
X
X /*
@@ -158,10 +159,8 @@
X
X DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
X
- DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
-
X /* Turn off interrupts */
- outb( 0, iobase+UART_IER);
+ outb(0, iobase+UART_IER);
X
X divisor = SPEED_MAX/speed;
X
@@ -170,55 +169,14 @@
X /* IrDA ports use 8N1 */
X lcr = UART_LCR_WLEN8;
X
- outb( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
- outb( divisor & 0xff, iobase+UART_DLL); /* Set speed */
- outb( divisor >> 8, iobase+UART_DLM);
- outb( lcr, iobase+UART_LCR); /* Set 8N1 */
- outb( fcr, iobase+UART_FCR); /* Enable FIFO's */
-
- /* Turn on interrups */
- outb( UART_IER_THRI|UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER);
-}
-
-/*
- * Function irport_interrupt (irq, dev_id, regs)
- *
- *
- */
-void irport_interrupt( int irq, void *dev_id, struct pt_regs *regs)
-{
- struct irda_device *idev = (struct irda_device *) dev_id;
-
- int iobase, status;
- int iir;
-
- DEBUG( 4, __FUNCTION__ "(), irq %d\n", irq);
-
- if ( !idev) {
- printk( KERN_WARNING __FUNCTION__
- "() irq %d for unknown device.\n", irq);
- return;
- }
-
- idev->netdev.interrupt = 1;
+ outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
+ outb(divisor & 0xff, iobase+UART_DLL); /* Set speed */
+ outb(divisor >> 8, iobase+UART_DLM);
+ outb(lcr, iobase+UART_LCR); /* Set 8N1 */
+ outb(fcr, iobase+UART_FCR); /* Enable FIFO's */
X
- iobase = idev->io.iobase2;
-
- iir = inb(iobase + UART_IIR);
- do {
- status = inb( iobase+UART_LSR);
-
- if (status & UART_LSR_DR) {
- /* Receive interrupt */
- irport_receive(idev);
- }
- if (status & UART_LSR_THRE) {
- /* Transmitter ready for data */


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

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

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part05

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


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.6 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

X * GDT ISA/EISA/PCI Disk Array Controller driver for Linux *
X * *
X * gdth.c *
- * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner *
+ * Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner *
X * *
X * <ac...@vortex.de> *
X * *
@@ -20,9 +20,34 @@
X * along with this kernel; if not, write to the Free Software *
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
X * *
- * Tested with Linux 1.2.13, ..., 2.1.131 *
+ * Tested with Linux 1.2.13, ..., 2.2.4 *
X * *
X * $Log: gdth.c,v $
+ * Revision 1.23 1999/03/26 09:12:31 achim
+ * Default value for hdr_channel set to 0
+ *
+ * Revision 1.22 1999/03/22 16:27:16 achim
+ * Bugfix: gdth_store_event() must not be locked with GDTH_LOCK_HA()
+ *
+ * Revision 1.21 1999/03/16 13:40:34 achim
+ * Problems with reserved drives solved
+ * gdth_eh_bus_reset() implemented
+ *
+ * Revision 1.20 1999/03/10 09:08:13 achim
+ * Bugfix: Corrections in gdth_direction_tab[] made
+ * Bugfix: Increase command timeout (gdth_update_timeout()) NOT in gdth_putq()
+ *
+ * Revision 1.19 1999/03/05 14:38:16 achim
+ * Bugfix: Heads/Sectors mapping for reserved devices possibly wrong
+ * -> gdth_eval_mapping() implemented, changes in gdth_bios_param()
+ * INIT_RETRIES set to 100s to avoid DEINIT-Timeout for controllers
+ * with BIOS disabled and memory test set to Intensive
+ * Enhanced /proc support
+ *
+ * Revision 1.18 1999/02/24 09:54:33 achim
+ * Command line parameter hdr_channel implemented
+ * Bugfix for EISA controllers + Linux 2.2.x
+ *
X * Revision 1.17 1998/12/17 15:58:11 achim
X * Command line parameters implemented
X * Changes for Alpha platforms
@@ -95,7 +120,7 @@
X * Initial revision
X *
X ************************************************************************/
-#ident "$Id: gdth.c,v 1.17 1998/12/17 15:58:11 achim Exp $"
+#ident "$Id: gdth.c,v 1.23 1999/03/26 09:12:31 achim Exp $"
X
X /* All GDT Disk Array Controllers are fully supported by this driver.
X * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -122,9 +147,10 @@
X * max_ids:x x - target ID count per channel (1..MAXID)
X * rescan:Y rescan all channels/IDs
X * rescan:N use all devices found until now
+ * hdr_channel:x x - number of virtual bus for host drives
X *
X * The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
- * max_ids:127,rescan:N".
+ * max_ids:127,rescan:N,hdr_channel:0".
X * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
X *
X * When loading the gdth driver as a module, the same options are available.
@@ -134,7 +160,7 @@
X * '1' in place of 'Y' and '0' in place of 'N'.
X *
X * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
- * max_ids=127 rescan=0"
+ * max_ids=127 rescan=0 hdr_channel=0"
X * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
X */
X
@@ -179,6 +205,8 @@
X
X #include "gdth.h"
X
+static void gdth_delay(int milliseconds);
+static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs);
X #if LINUX_VERSION_CODE >= 0x010346
X static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
X #else
@@ -186,7 +214,7 @@
X #endif
X static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
X static int gdth_async_event(int hanum,int service);
-static void gdth_log_event(gdth_evt_data *dvr);
+static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
X
X static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
X static void gdth_next(int hanum);
@@ -226,6 +254,7 @@
X
X static const char *gdth_ctr_name(int hanum);
X
+#if LINUX_VERSION_CODE >= 0x010300
X static void gdth_flush(int hanum);
X #if LINUX_VERSION_CODE >= 0x020100
X static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
@@ -233,6 +262,7 @@
X static int halt_called = FALSE;
X void gdth_halt(void);
X #endif
+#endif
X
X #ifdef DEBUG_GDTH
X static unchar DebugState = DEBUG_GDTH;
@@ -331,6 +361,7 @@
X #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
X #define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
X
+#define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b))
X
X #if LINUX_VERSION_CODE < 0x010300
X static void *gdth_mmap(ulong paddr, ulong size)
@@ -429,16 +460,16 @@
X static unchar gdth_direction_tab[0x100] = {
X DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
X DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
- DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DIN,DUN,DUN,DIN,DIN,DIN,
- DIN,DIN,DIN,DNO,DIN,DNO,DNO,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,
- DIN,DIN,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DIN,DIN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
+ DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
+ DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
+ DOU,DOU,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DUN,DUN,
+ DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DIN,DUN,DNO,DUN,DIN,DIN,
- DIN,DIN,DIN,DNO,DUN,DIN,DIN,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
+ DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
+ DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
X DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
@@ -474,25 +505,6 @@
X #define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0)
X #endif
X
-/* /proc support */
-#if LINUX_VERSION_CODE >= 0x010300
-#include <linux/stat.h>
-struct proc_dir_entry proc_scsi_gdth = {
- PROC_SCSI_GDTH, 4, "gdth",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-#include "gdth_proc.h"
-#include "gdth_proc.c"
-#endif
-
-#if LINUX_VERSION_CODE >= 0x020100
-/* notifier block to get a notify on system shutdown/halt/reboot */
-static struct notifier_block gdth_notifier = {
- gdth_halt, NULL, 0
-};
-#endif
-
-
X /* LILO and modprobe/insmod parameters */
X /* IRQ list for GDT3000/3020 EISA controllers */
X static int irq[MAXHA] __initdata =
@@ -501,14 +513,16 @@
X /* disable driver flag */
X static int disable __initdata = 0;
X /* reserve flag */
-static int reserve_mode __initdata = 1;
+static int reserve_mode = 1;
X /* reserve list */
-static int reserve_list[MAX_RES_ARGS] __initdata =
+static int reserve_list[MAX_RES_ARGS] =
X {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
X 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
X 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
X /* scan order for PCI controllers */
-static int reverse_scan __initdata = 0;
+static int reverse_scan = 0;
+/* virtual channel for the host drives */
+static int hdr_channel = 0;
X /* max. IDs per channel */
X static int max_ids = MAXID;
X /* rescan all IDs */
@@ -522,12 +536,31 @@
X MODULE_PARM(reserve_mode, "i");
X MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
X MODULE_PARM(reverse_scan, "i");
+MODULE_PARM(hdr_channel, "i");
X MODULE_PARM(max_ids, "i");
X MODULE_PARM(rescan, "i");
X MODULE_AUTHOR("Achim Leubner");
X #endif
X #endif
X
+/* /proc support */
+#if LINUX_VERSION_CODE >= 0x010300
+#include <linux/stat.h>
+struct proc_dir_entry proc_scsi_gdth = {
+ PROC_SCSI_GDTH, 4, "gdth",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#include "gdth_proc.h"
+#include "gdth_proc.c"
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020100
+/* notifier block to get a notify on system shutdown/halt/reboot */
+static struct notifier_block gdth_notifier = {
+ gdth_halt, NULL, 0
+};
+#endif
+
X
X static void gdth_delay(int milliseconds)
X {
@@ -544,6 +577,25 @@
X }
X }
X
+static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs)
+{
+ *cyls = size /HEADS/SECS;
+ if (*cyls <= MAXCYLS) {
+ *heads = HEADS;
+ *secs = SECS;
+ } else { /* too high for 64*32 */
+ *cyls = size /MEDHEADS/MEDSECS;
+ if (*cyls <= MAXCYLS) {
+ *heads = MEDHEADS;
+ *secs = MEDSECS;
+ } else { /* too high for 127*63 */
+ *cyls = size /BIGHEADS/BIGSECS;
+ *heads = BIGHEADS;
+ *secs = BIGSECS;
+ }
+ }
+}
+
X /* controller search and initialization functions */
X
X __initfunc (static int gdth_search_eisa(ushort eisa_adr))
@@ -1413,9 +1465,9 @@
X ha->pccb->Service |= 0x80;
X
X if (ha->type == GDT_EISA) {
- outb(ha->pccb->Service, ha->bmic + LDOORREG);
X if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */
- outl((ulong)ha->pccb, ha->bmic + MAILBOXREG);
+ outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG);
+ outb(ha->pccb->Service, ha->bmic + LDOORREG);
X } else if (ha->type == GDT_ISA) {
X gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
X } else if (ha->type == GDT_PCI) {
@@ -1526,11 +1578,15 @@
X {
X register gdth_ha_str *ha;
X ushort cdev_cnt, i;
- ulong32 drv_cyls, drv_hds, drv_secs;
+ int drv_cyls, drv_hds, drv_secs;
X ulong32 bus_no;
+ ulong32 drv_cnt, drv_no, j;
X gdth_getch_str *chn;
+ gdth_drlist_str *drl;
X gdth_iochan_str *ioc;
-
+ gdth_raw_iochan_str *iocr;
+ gdth_arraylist_str *alst;
+
X TRACE(("gdth_search_drives() hanum %d\n",hanum));
X ha = HADATA(gdth_ctr_tab[hanum]);
X
@@ -1565,19 +1621,19 @@
X cdev_cnt = (ushort)ha->info;
X
X /* detect number of buses - try new IOCTL */
- ioc = (gdth_iochan_str *)ha->pscratch;
- ioc->version = 0xffffffff;
- ioc->list_entries = MAXBUS;
- ioc->first_chan = 0;
- ioc->last_chan = MAXBUS-1;
- ioc->list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
- if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC,
- INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
- TRACE2(("GET_IOCHAN_DESC supported!\n"));
- ha->bus_cnt = ioc->chan_count;
+ iocr = (gdth_raw_iochan_str *)ha->pscratch;
+ iocr->hdr.version = 0xffffffff;
+ iocr->hdr.list_entries = MAXBUS;
+ iocr->hdr.first_chan = 0;
+ iocr->hdr.last_chan = MAXBUS-1;
+ iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC,
+ INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
+ TRACE2(("IOCHAN_RAW_DESC supported!\n"));
+ ha->bus_cnt = iocr->hdr.chan_count;
X for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
- if (ioc->list[bus_no].proc_id < MAXID)
- ha->bus_id[bus_no] = ioc->list[bus_no].proc_id;
+ if (iocr->list[bus_no].proc_id < MAXID)
+ ha->bus_id[bus_no] = iocr->list[bus_no].proc_id;
X else
X ha->bus_id[bus_no] = 0xff;
X }
@@ -1618,16 +1674,100 @@
X ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
X ha->cpar.write_back,ha->cpar.block_size));
X
- /* read board info, fill ctr_name[] */
+ /* read board info and features */
+ ha->more_proc = FALSE;
X if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
X INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
- TRACE2(("BOARD_INFO supported!\n"));
- strcpy(ha->ctr_name, ((gdth_binfo_str *)ha->pscratch)->type_string);
+ ha->binfo = *(gdth_binfo_str *)ha->pscratch;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES,
+ INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
+ TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
+ ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
+ ha->more_proc = TRUE;
+ }
X } else {
- strcpy(ha->ctr_name, gdth_ctr_name(hanum));
+ TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
+ strcpy(ha->binfo.type_string, gdth_ctr_name(hanum));
X }
- TRACE2(("Controller name: %s\n",ha->ctr_name));
+ TRACE2(("Controller name: %s\n",ha->binfo.type_string));
X
+ /* read more informations */
+ if (ha->more_proc) {
+ /* physical drives, channel addresses */
+ ioc = (gdth_iochan_str *)ha->pscratch;
+ ioc->hdr.version = 0xffffffff;
+ ioc->hdr.list_entries = MAXBUS;
+ ioc->hdr.first_chan = 0;
+ ioc->hdr.last_chan = MAXBUS-1;
+ ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC,
+ INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ ha->raw[bus_no].address = ioc->list[bus_no].address;
+ ha->raw[bus_no].local_no = ioc->list[bus_no].local_no;
+ }
+ } else {
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ ha->raw[bus_no].address = IO_CHANNEL;
+ ha->raw[bus_no].local_no = bus_no;
+ }
+ }
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ chn = (gdth_getch_str *)ha->pscratch;
+ chn->channel_no = ha->raw[bus_no].local_no;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ SCSI_CHAN_CNT | L_CTRL_PATTERN,
+ ha->raw[bus_no].address | INVALID_CHANNEL,
+ sizeof(gdth_getch_str))) {
+ ha->raw[bus_no].pdev_cnt = chn->drive_cnt;
+ TRACE2(("Channel %d: %d phys. drives\n",
+ bus_no,chn->drive_cnt));
+ }
+ if (ha->raw[bus_no].pdev_cnt > 0) {
+ drl = (gdth_drlist_str *)ha->pscratch;
+ drl->sc_no = ha->raw[bus_no].local_no;
+ drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ SCSI_DR_LIST | L_CTRL_PATTERN,
+ ha->raw[bus_no].address | INVALID_CHANNEL,
+ sizeof(gdth_drlist_str))) {
+ for (j = 0; j < ha->raw[bus_no].pdev_cnt; ++j)
+ ha->raw[bus_no].id_list[j] = drl->sc_list[j];
+ } else {
+ ha->raw[bus_no].pdev_cnt = 0;
+ }
+ }
+ }
+
+ /* logical drives */
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT,
+ INVALID_CHANNEL,sizeof(ulong32))) {
+ drv_cnt = *(ulong32 *)ha->pscratch;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST,
+ INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
+ for (j = 0; j < drv_cnt; ++j) {
+ drv_no = ((ulong32 *)ha->pscratch)[j];
+ if (drv_no < MAX_HDRIVES) {
+ ha->hdr[drv_no].is_logdrv = TRUE;
+ TRACE2(("Drive %d is log. drive\n",drv_no));
+ }
+ }
+ }
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ ARRAY_DRV_LIST | LA_CTRL_PATTERN,
+ 0, 35 * sizeof(gdth_arraylist_str))) {
+ for (j = 0; j < 35; ++j) {
+ alst = &((gdth_arraylist_str *)ha->pscratch)[j];
+ ha->hdr[j].is_arraydrv = alst->is_arrayd;
+ ha->hdr[j].is_master = alst->is_master;
+ ha->hdr[j].is_parity = alst->is_parity;
+ ha->hdr[j].is_hotfix = alst->is_hotfix;
+ ha->hdr[j].master_no = alst->cd_handle;


+ }
+ }
+ }
+ }
+

X /* initialize raw service */
X if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
X printk("GDT: Initialization error raw service (code %d)\n",
@@ -1695,21 +1835,7 @@
X /* evaluate mapping (sectors per head, heads per cylinder) */
X ha->hdr[i].size &= ~SECS32;
X if (ha->info2 == 0) {
- drv_cyls = ha->hdr[i].size /HEADS/SECS;
- if (drv_cyls <= MAXCYLS) {
- drv_hds = HEADS;
- drv_secs= SECS;
- } else { /* too high for 64*32 */
- drv_cyls = ha->hdr[i].size /MEDHEADS/MEDSECS;
- if (drv_cyls <= MAXCYLS) {
- drv_hds = MEDHEADS;
- drv_secs= MEDSECS;
- } else { /* too high for 127*63 */
- drv_cyls = ha->hdr[i].size /BIGHEADS/BIGSECS;
- drv_hds = BIGHEADS;
- drv_secs= BIGSECS;
- }
- }
+ gdth_eval_mapping(ha->hdr[i].size,&drv_cyls,&drv_hds,&drv_secs);
X } else {
X drv_hds = ha->info2 & 0xff;
X drv_secs = (ha->info2 >> 8) & 0xff;
@@ -1752,7 +1878,6 @@
X GDTH_LOCK_HA(ha, flags);
X
X scp->SCp.this_residual = (int)priority;
- gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
X #if LINUX_VERSION_CODE >= 0x020000
X b = scp->channel;
X #else
@@ -1761,8 +1886,8 @@
X t = scp->target;
X #if LINUX_VERSION_CODE >= 0x010300
X if (priority >= DEFAULT_PRI) {
- if ((b < ha->bus_cnt && ha->raw[b].lock) ||
- (b == ha->bus_cnt && ha->hdr[t].lock)) {
+ if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+ (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
X TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
X scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
X }
@@ -1825,8 +1950,8 @@
X #endif
X t = nscp->target;
X if (nscp->SCp.this_residual >= DEFAULT_PRI) {
- if ((b < ha->bus_cnt && ha->raw[b].lock) ||
- (b == ha->bus_cnt && ha->hdr[t].lock))
+ if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+ (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
X continue;
X }
X
@@ -1843,22 +1968,24 @@
X firsttime = FALSE;
X }
X
+#if LINUX_VERSION_CODE >= 0x010300
+ if (nscp->done != gdth_scsi_done)
+#endif
+ {
X if (nscp->SCp.phase == -1) {
X nscp->SCp.phase = SCSIRAWSERVICE; /* default: raw svc. */
X if (nscp->cmnd[0] == TEST_UNIT_READY) {
- TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
- nscp->channel, nscp->target, nscp->lun));
+ TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
+ b, t, nscp->lun));
X /* TEST_UNIT_READY -> set scan mode */
X if ((ha->scan_mode & 0x0f) == 0) {
- if (nscp->channel == 0 && nscp->target == 0 &&
- nscp->lun == 0) {
+ if (b == 0 && t == 0 && nscp->lun == 0) {
X ha->scan_mode |= 1;
X TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
X }
X } else if ((ha->scan_mode & 0x0f) == 1) {
- if (nscp->channel == 0 &&
- ((nscp->target == 0 && nscp->lun == 1) ||
- (nscp->target == 1 && nscp->lun == 0))) {
+ if (b == 0 && ((t == 0 && nscp->lun == 1) ||
+ (t == 1 && nscp->lun == 0))) {
X nscp->SCp.Status = GDT_SCAN_START;
X nscp->SCp.phase |= ((ha->scan_mode & 0x10 ? 1:0) << 8);
X ha->scan_mode = 0x12;
@@ -1869,7 +1996,7 @@
X TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
X }
X } else if (ha->scan_mode == 0x12) {
- if (b == ha->bus_cnt) {
+ if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
X nscp->SCp.Status = GDT_SCAN_END;
X ha->scan_mode &= 0x10;
X TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
@@ -1878,10 +2005,12 @@
X }
X }
X }
+ }
X
X if (nscp->SCp.Status != -1) {
X if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
- cmd_index=gdth_fill_raw_cmd(hanum,nscp,b);
+ if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
+ this_cmd = FALSE;
X next_cmd = FALSE;
X }
X } else
@@ -1893,13 +2022,15 @@
X next_cmd = FALSE;
X } else
X #endif
- if (b < ha->bus_cnt) {
- if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) {
+ if (b != ha->virt_bus) {
+ if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
+ !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
X this_cmd = FALSE;
- }
- } else if (!ha->hdr[nscp->target].present || nscp->lun != 0) {
+ else
+ ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
+ } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || nscp->lun != 0) {
X TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
- nscp->cmnd[0], b, nscp->target, nscp->lun));
+ nscp->cmnd[0], b, t, nscp->lun));
X nscp->result = DID_BAD_TARGET << 16;
X GDTH_UNLOCK_HA(ha,flags);
X /* io_request_lock already active ! */
@@ -2405,14 +2536,13 @@
X ushort idx, gdth_evt_data *evt)
X {
X gdth_evt_str *e;
- ulong flags;
X struct timeval tv;
X
+ /* no GDTH_LOCK_HA() ! */
X TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
X if (source == 0) /* no source -> no event */
X return 0;
X
- GDTH_LOCK_HA(ha, flags);
X if (ebuffer[elastidx].event_source == source &&
X ebuffer[elastidx].event_idx == idx &&
X !memcmp((char *)&ebuffer[elastidx].event_data.eu,
@@ -2440,7 +2570,6 @@
X e->same_count = 1;
X e->event_data = *evt;
X }
- GDTH_UNLOCK_HA(ha, flags);
X return e;
X }
X
@@ -2808,9 +2937,12 @@
X printk("\n");
X
X } else {
- scp->SCp.Message = (int)ha->status;
+ if (scp->SCp.Status == -1 && scp->channel != ha->virt_bus) {
+ ha->raw[BUS_L2P(ha,scp->channel)].io_cnt[scp->target]--;
+ }
X /* cache or raw service */
X if (ha->status == S_OK) {
+ scp->SCp.Message = S_OK;
X if (scp->SCp.Status != -1) {
X TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
X scp->SCp.Status));
@@ -2821,8 +2953,10 @@
X scp->result = DID_OK << 16;
X } else if (ha->status == S_BSY) {
X TRACE2(("Controller busy -> retry !\n"));
+ scp->SCp.Message = S_BSY;
X return 2;
X } else {
+ scp->SCp.Message = (int)((ha->info<<16)|ha->status);
X if (scp->SCp.Status != -1) {
X TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
X scp->SCp.Status, ha->status));
@@ -2836,7 +2970,10 @@
X scp->sense_buffer[2] = NOT_READY;
X scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
X
- if (scp->done != gdth_scsi_done) {
+#if LINUX_VERSION_CODE >= 0x010300
+ if (scp->done != gdth_scsi_done)
+#endif
+ {
X dvr.size = sizeof(dvr.eu.sync);
X dvr.eu.sync.ionode = hanum;
X dvr.eu.sync.service = service;
@@ -2904,7 +3041,7 @@
X "GDT HA %u, Array Drive %u: parity build failed",
X /*18*/ "\005\000\002\006\002"
X "GDT HA %u, Array Drive %u: drive rebuild failed",
-/*19*/ "\007\000\002\010\002"
+/*19*/ "\005\000\002\010\002"
X "GDT HA %u, Test of Hot Fix %u failed",
X /*20*/ "\005\000\002\006\002"
X "GDT HA %u, Array Drive %u: drive build finished successfully",
@@ -3066,12 +3203,12 @@
X dvr.eu.async.info = ha->info;
X *(ulong32 *)dvr.eu.async.scsi_coord = ha->info2;
X gdth_store_event(ha, ES_ASYNC, service, &dvr);
- gdth_log_event( &dvr );
+ gdth_log_event( &dvr, NULL );
X }
X return 1;
X }
X
-static void gdth_log_event(gdth_evt_data *dvr)
+static void gdth_log_event(gdth_evt_data *dvr, char *buffer)
X {
X gdth_stackframe stack;
X char *f = NULL;
@@ -3101,12 +3238,22 @@


X break;
X }
X }
-

- printk(&f[(int)f[0]],stack); printk("\n");
+
+ if (buffer == NULL) {
+ printk(&f[(int)f[0]],stack);
+ printk("\n");
+ } else {
+ sprintf(buffer,&f[(int)f[0]],stack);
+ }
X
X } else {
- printk("GDT: Unknown async. event service %d event no. %d\n",
- dvr->eu.async.service,dvr->eu.async.status);
+ if (buffer == NULL) {
+ printk("GDT HA %u, Unknown async. event service %d event no. %d\n",
+ dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
+ } else {
+ sprintf(buffer,"GDT HA %u, Unknown async. event service %d event no. %d",
+ dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
+ }
X }
X }
X
@@ -3249,6 +3396,9 @@
X scsi_unregister(shp);
X continue;
X }
+ if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+ hdr_channel = ha->bus_cnt;
+ ha->virt_bus = hdr_channel;
X
X #if LINUX_VERSION_CODE >= 0x020000
X shp->max_id = ha->tid_cnt;
@@ -3333,6 +3483,9 @@
X scsi_unregister(shp);
X continue;
X }
+ if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+ hdr_channel = ha->bus_cnt;
+ ha->virt_bus = hdr_channel;
X
X #if LINUX_VERSION_CODE >= 0x020000
X shp->max_id = ha->tid_cnt;
@@ -3429,6 +3582,9 @@
X scsi_unregister(shp);
X continue;
X }
+ if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+ hdr_channel = ha->bus_cnt;
+ ha->virt_bus = hdr_channel;
X
X #if LINUX_VERSION_CODE >= 0x020000
X shp->max_id = ha->tid_cnt;
@@ -3479,7 +3635,9 @@
X if (NUMDATA(shp)->busnum == 0) {
X hanum = NUMDATA(shp)->hanum;
X ha = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= 0x010300
X gdth_flush(hanum);
+#endif
X
X if (shp->irq) {
X #if LINUX_VERSION_CODE >= 0x010346
@@ -3552,7 +3710,7 @@
X hanum = NUMDATA(shp)->hanum;
X ha = HADATA(gdth_ctr_tab[hanum]);
X
- return ((const char *)ha->ctr_name);
+ return ((const char *)ha->binfo.type_string);
X }
X
X /* old error handling */
@@ -3588,8 +3746,33 @@
X
X int gdth_eh_bus_reset(Scsi_Cmnd *scp)
X {
+ int i, hanum;
+ gdth_ha_str *ha;
+ ulong flags;
+ Scsi_Cmnd *cmnd;
+
X TRACE2(("gdth_eh_bus_reset()\n"));
- return FAILED;
+ hanum = NUMDATA(scp->host)->hanum;
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ if (scp->channel == ha->virt_bus)
+ return FAILED;
+
+ GDTH_LOCK_HA(ha, flags);
+ for (i = 0; i < MAXID; ++i)
+ ha->raw[BUS_L2P(ha,scp->channel)].io_cnt[i] = 0;
+ for (i = 0; i < GDTH_MAXCMDS; ++i) {
+ cmnd = ha->cmd_tab[i].cmnd;
+ if (!SPECIAL_SCP(cmnd) && cmnd->channel == scp->channel)
+ ha->cmd_tab[i].cmnd = UNUSED_CMND;
+ }
+ gdth_polling = TRUE;
+ while (gdth_test_busy(hanum))
+ gdth_delay(0);
+ gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
+ BUS_L2P(ha,scp->channel), 0, 0);
+ gdth_polling = FALSE;
+ GDTH_UNLOCK_HA(ha, flags);
+ return SUCCESS;
X }
X
X int gdth_eh_host_reset(Scsi_Cmnd *scp)
@@ -3608,7 +3791,6 @@
X unchar t;
X int hanum;
X gdth_ha_str *ha;
- int drv_hds, drv_secs;
X
X hanum = NUMDATA(disk->device->host)->hanum;
X t = disk->device->id;
@@ -3616,27 +3798,16 @@
X hanum, disk->device->channel, t));
X ha = HADATA(gdth_ctr_tab[hanum]);
X
- if (ha->hdr[t].heads == 0) {
- /* raw device: evaluate mapping (sectors per head, heads per cylinder) */
- if (disk->capacity /HEADS/SECS <= MAXCYLS) {
- drv_hds = HEADS;
- drv_secs= SECS;
- } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) {
- drv_hds = MEDHEADS;
- drv_secs= MEDSECS;
- } else {
- drv_hds = BIGHEADS;
- drv_secs= BIGSECS;
- }
- ha->hdr[t].heads = drv_hds;
- ha->hdr[t].secs = drv_secs;
- TRACE2(("gdth_bios_param(): raw device -> params evaluated\n"));
+ if (disk->device->channel != ha->virt_bus || ha->hdr[t].heads == 0) {
+ /* raw device or host drive without mapping information */
+ TRACE2(("Evaluate mapping\n"));
+ gdth_eval_mapping(disk->capacity,&ip[2],&ip[0],&ip[1]);
+ } else {
+ ip[0] = ha->hdr[t].heads;
+ ip[1] = ha->hdr[t].secs;
+ ip[2] = disk->capacity / ip[0] / ip[1];
X }
X
- ip[0] = ha->hdr[t].heads;
- ip[1] = ha->hdr[t].secs;
- ip[2] = disk->capacity / ip[0] / ip[1];
-
X TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
X ip[0],ip[1],ip[2]));
X return 0;
@@ -3683,11 +3854,13 @@
X if (scp->done == gdth_scsi_done)
X priority = scp->SCp.this_residual;
X #endif
+ gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
X gdth_putq( hanum, scp, priority );
X gdth_next( hanum );


X return 0;
X }
X

+#if LINUX_VERSION_CODE >= 0x010300
X /* flush routine */
X static void gdth_flush(int hanum)
X {
@@ -3696,7 +3869,6 @@
X Scsi_Cmnd scp;
X Scsi_Device sdev;
X gdth_cmd_str gdtcmd;
- char cmnd[12];
X
X TRACE2(("gdth_flush() hanum %d\n",hanum));
X ha = HADATA(gdth_ctr_tab[hanum]);
@@ -3719,18 +3891,7 @@
X gdtcmd.u.cache.BlockNo = 1;
X gdtcmd.u.cache.sg_canz = 0;
X TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 30*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
+ gdth_do_cmd(&scp, &gdtcmd, 30);
X }
X }
X }
@@ -3747,7 +3908,6 @@
X Scsi_Cmnd scp;
X Scsi_Device sdev;
X gdth_cmd_str gdtcmd;
- char cmnd[12];
X #endif
X
X #if LINUX_VERSION_CODE >= 0x020100
@@ -3782,18 +3942,7 @@
X gdtcmd.Service = CACHESERVICE;
X gdtcmd.OpCode = GDT_RESET;
X TRACE2(("gdth_halt(): reset controller %d\n", hanum));
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 10*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
+ gdth_do_cmd(&scp, &gdtcmd, 10);
X #endif
X }
X printk("Done.\n");
@@ -3806,6 +3955,7 @@
X return NOTIFY_OK;
X #endif
X }
+#endif
X
X
X /* called from init/main.c */
@@ -3846,6 +3996,8 @@
X reserve_mode = val;
X else if (!strncmp(argv, "reverse_scan:", 13))
X reverse_scan = val;
+ else if (!strncmp(argv, "hdr_channel:", 12))
+ hdr_channel = val;
X else if (!strncmp(argv, "max_ids:", 8))
X max_ids = val;
X else if (!strncmp(argv, "rescan:", 7))
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h
--- v2.2.5/linux/drivers/scsi/gdth.h Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/gdth.h Fri Apr 16 14:28:51 1999
@@ -4,13 +4,13 @@
X /*
X * Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux
X *
- * gdth.h Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner
+ * gdth.h Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner
X * See gdth.c for further informations and
X * below for supported controller types
X *
X * <ac...@vortex.de>
X *
- * $Id: gdth.h,v 1.16 1998/12/17 15:54:53 achim Exp $
+ * $Id: gdth.h,v 1.21 1999/03/26 09:12:24 achim Exp $
X */
X
X #include <linux/version.h>
@@ -29,9 +29,9 @@
X /* defines, macros */
X
X /* driver version */
-#define GDTH_VERSION_STR "1.10"
+#define GDTH_VERSION_STR "1.14"
X #define GDTH_VERSION 1
-#define GDTH_SUBVERSION 10
+#define GDTH_SUBVERSION 14
X
X /* protocol version */
X #define PROTOCOL_VERSION 1
@@ -129,6 +129,7 @@
X #define GDTH_SCRATCH 4096 /* 4KB scratch buffer */
X #define GDTH_MAXCMDS 124
X #define GDTH_MAXC_P_L 16 /* max. cmds per lun */
+#define GDTH_MAX_RAW 2 /* max. cmds per raw device */
X #define MAXOFFSETS 128
X #define MAXHA 16
X #define MAXID 127
@@ -199,14 +200,27 @@
X #define GDT_SCAN_END 20 /* stop device scan */
X
X /* IOCTL command defines */
-#define SCSI_CHAN_CNT 5 /* subfunctions */
-#define GET_IOCHAN_DESC 0x5e
-#define L_CTRL_PATTERN 0x20000000L
-#define CACHE_INFO 4
-#define CACHE_CONFIG 5
-#define BOARD_INFO 0x28
-#define IO_CHANNEL 0x00020000L /* channels */
-#define INVALID_CHANNEL 0x0000ffffL
+#define SCSI_DR_INFO 0x00 /* SCSI drive info */
+#define SCSI_CHAN_CNT 0x05 /* SCSI channel count */
+#define SCSI_DR_LIST 0x06 /* SCSI drive list */
+#define SCSI_DEF_CNT 0x15 /* grown/primary defects */
+#define DSK_STATISTICS 0x4b /* SCSI disk statistics */
+#define IOCHAN_DESC 0x5d /* description of IO channel */
+#define IOCHAN_RAW_DESC 0x5e /* description of raw IO channel */
+#define L_CTRL_PATTERN 0x20000000L /* SCSI IOCTL mask */
+#define ARRAY_INFO 0x12 /* array drive info */
+#define ARRAY_DRV_LIST 0x0f /* array drive list */
+#define LA_CTRL_PATTERN 0x10000000L /* array IOCTL mask */
+#define CACHE_DRV_CNT 0x01 /* cache drive count */
+#define CACHE_DRV_LIST 0x02 /* cache drive list */
+#define CACHE_INFO 0x04 /* cache info */
+#define CACHE_CONFIG 0x05 /* cache configuration */
+#define CACHE_DRV_INFO 0x07 /* cache drive info */
+#define BOARD_FEATURES 0x15 /* controller features */
+#define BOARD_INFO 0x28 /* controller info */
+#define HOST_GET 0x10001L /* get host drive list */
+#define IO_CHANNEL 0x00020000L /* default IO channel */
+#define INVALID_CHANNEL 0x0000ffffL /* invalid channel */
X
X /* IOCTLs */
X #define GDTIOCTL_MASK ('J'<<8)
@@ -225,8 +239,8 @@
X #define S_RAW_ILL 0xff /* raw serv.: illegal */
X
X /* timeout values */
-#define INIT_RETRIES 10000 /* 10000 * 1ms = 10s */
-#define INIT_TIMEOUT 100000 /* 1000 * 1ms = 1s */
+#define INIT_RETRIES 100000 /* 100000 * 1ms = 100s */
+#define INIT_TIMEOUT 100000 /* 100000 * 1ms = 100s */
X #define POLL_TIMEOUT 10000 /* 10000 * 1ms = 10s */
X
X /* priorities */
@@ -276,29 +290,171 @@
X char msg_text[MSGLEN+2]; /* the message text */
X } PACKED gdth_msg_str;
X
-/* get channel count IOCTL */
+/* IOCTL data structures */
+/* SCSI drive info */
+typedef struct {
+ unchar vendor[8]; /* vendor string */
+ unchar product[16]; /* product string */
+ unchar revision[4]; /* revision */
+ ulong32 sy_rate; /* current rate for sync. tr. */
+ ulong32 sy_max_rate; /* max. rate for sync. tr. */
+ ulong32 no_ldrive; /* belongs to this logical drv.*/
+ ulong32 blkcnt; /* number of blocks */
+ ushort blksize; /* size of block in bytes */
+ unchar available; /* flag: access is available */
+ unchar init; /* medium is initialized */
+ unchar devtype; /* SCSI devicetype */
+ unchar rm_medium; /* medium is removable */
+ unchar wp_medium; /* medium is write protected */
+ unchar ansi; /* SCSI I/II or III? */
+ unchar protocol; /* same as ansi */
+ unchar sync; /* flag: sync. transfer enab. */
+ unchar disc; /* flag: disconnect enabled */
+ unchar queueing; /* flag: command queing enab. */
+ unchar cached; /* flag: caching enabled */
+ unchar target_id; /* target ID of device */
+ unchar lun; /* LUN id of device */
+ unchar orphan; /* flag: drive fragment */
+ ulong32 last_error; /* sense key or drive state */
+ ulong32 last_result; /* result of last command */
+ ulong32 check_errors; /* err. in last surface check */
+ unchar percent; /* progress for surface check */
+ unchar last_check; /* IOCTRL operation */
+ unchar res[2];
+ ulong32 flags; /* from 1.19/2.19: raw reserv.*/
+ unchar multi_bus; /* multi bus dev? (fibre ch.) */
+ unchar mb_status; /* status: available? */
+ unchar res2[2];
+ unchar mb_alt_status; /* status on second bus */
+ unchar mb_alt_bid; /* number of second bus */
+ unchar mb_alt_tid; /* target id on second bus */
+ unchar res3;
+ unchar fc_flag; /* from 1.22/2.22: info valid?*/
+ unchar res4;
+ ushort fc_frame_size; /* frame size (bytes) */
+ char wwn[8]; /* world wide name */
+} PACKED gdth_diskinfo_str;
+
+/* get SCSI channel count */
X typedef struct {
X ulong32 channel_no; /* number of channel */
- ulong32 drive_cnt; /* number of drives */
+ ulong32 drive_cnt; /* drive count */
X unchar siop_id; /* SCSI processor ID */
X unchar siop_state; /* SCSI processor state */
X } PACKED gdth_getch_str;
X
-/* get raw channel count IOCTL (NEW!) */
+/* get SCSI drive numbers */
X typedef struct {
- ulong32 version; /* version of information (-1UL: newest) */
- unchar list_entries; /* list entry count */
- unchar first_chan; /* first channel number */
- unchar last_chan; /* last channel number */
- unchar chan_count; /* (R) channel count */
- ulong32 list_offset; /* offset of list[0] */
+ ulong32 sc_no; /* SCSI channel */
+ ulong32 sc_cnt; /* sc_list[] elements */
+ ulong32 sc_list[MAXID]; /* minor device numbers */
+} PACKED gdth_drlist_str;
+
+/* get grown/primary defect count */
+typedef struct {
+ unchar sddc_type; /* 0x08: grown, 0x10: prim. */
+ unchar sddc_format; /* list entry format */
+ unchar sddc_len; /* list entry length */
+ unchar sddc_res;
+ ulong32 sddc_cnt; /* entry count */
+} PACKED gdth_defcnt_str;
+
+/* disk statistics */
+typedef struct {
+ ulong32 bid; /* SCSI channel */
+ ulong32 first; /* first SCSI disk */
+ ulong32 entries; /* number of elements */
+ ulong32 count; /* (R) number of init. el. */
+ ulong32 mon_time; /* time stamp */
X struct {
- unchar proc_id; /* processor id */
- unchar proc_defect; /* defect ? */
- unchar reserved[2];
+ unchar tid; /* target ID */
+ unchar lun; /* LUN */
+ unchar res[2];
+ ulong32 blk_size; /* block size in bytes */
+ ulong32 rd_count; /* bytes read */
+ ulong32 wr_count; /* bytes written */
+ ulong32 rd_blk_count; /* blocks read */
+ ulong32 wr_blk_count; /* blocks written */
+ ulong32 retries; /* retries */
+ ulong32 reassigns; /* reassigns */
+ } PACKED list[1];
+} PACKED gdth_dskstat_str;
+
+/* IO channel header */
+typedef struct {
+ ulong32 version; /* version (-1UL: newest) */
+ unchar list_entries; /* list entry count */
+ unchar first_chan; /* first channel number */
+ unchar last_chan; /* last channel number */
+ unchar chan_count; /* (R) channel count */
+ ulong32 list_offset; /* offset of list[0] */
+} PACKED gdth_iochan_header;
+
+/* get IO channel description */
+typedef struct {
+ gdth_iochan_header hdr;
+ struct {
+ ulong32 address; /* channel address */
+ unchar type; /* type (SCSI, FCAL) */
+ unchar local_no; /* local number */
+ ushort features; /* channel features */
X } PACKED list[MAXBUS];
X } PACKED gdth_iochan_str;
X
+/* get raw IO channel description */
+typedef struct {
+ gdth_iochan_header hdr;
+ struct {
+ unchar proc_id; /* processor id */
+ unchar proc_defect; /* defect ? */
+ unchar reserved[2];
+ } PACKED list[MAXBUS];
+} PACKED gdth_raw_iochan_str;
+
+/* array drive component */
+typedef struct {
+ ulong32 al_controller; /* controller ID */
+ unchar al_cache_drive; /* cache drive number */
+ unchar al_status; /* cache drive state */
+ unchar al_res[2];
+} PACKED gdth_arraycomp_str;
+
+/* array drive information */
+typedef struct {
+ unchar ai_type; /* array type (RAID0,4,5) */
+ unchar ai_cache_drive_cnt; /* active cachedrives */
+ unchar ai_state; /* array drive state */
+ unchar ai_master_cd; /* master cachedrive */
+ ulong32 ai_master_controller; /* ID of master controller */
+ ulong32 ai_size; /* user capacity [sectors] */
+ ulong32 ai_striping_size; /* striping size [sectors] */
+ ulong32 ai_secsize; /* sector size [bytes] */
+ ulong32 ai_err_info; /* failed cache drive */
+ unchar ai_name[8]; /* name of the array drive */
+ unchar ai_controller_cnt; /* number of controllers */
+ unchar ai_removable; /* flag: removable */
+ unchar ai_write_protected; /* flag: write protected */
+ unchar ai_devtype; /* type: always direct access */
+ gdth_arraycomp_str ai_drives[35]; /* drive components: */
+ unchar ai_drive_entries; /* number of drive components */
+ unchar ai_protected; /* protection flag */
+ unchar ai_verify_state; /* state of a parity verify */
+ unchar ai_ext_state; /* extended array drive state */
+ unchar ai_expand_state; /* array expand state (>=2.18)*/
+ unchar ai_reserved[3];
+} PACKED gdth_arrayinf_str;
+
+/* get array drive list */
+typedef struct {
+ ulong32 controller_no; /* controller no. */
+ unchar cd_handle; /* master cachedrive */
+ unchar is_arrayd; /* Flag: is array drive? */
+ unchar is_master; /* Flag: is array master? */
+ unchar is_parity; /* Flag: is parity drive? */
+ unchar is_hotfix; /* Flag: is hotfix drive? */
+ unchar res[3];
+} PACKED gdth_arraylist_str;
+
X /* cache info/config IOCTL */
X typedef struct {
X ulong32 version; /* firmware version */
@@ -322,6 +478,34 @@
X gdth_cstat_str cstat;
X } PACKED gdth_cinfo_str;
X
+/* cache drive info */
+typedef struct {
+ unchar cd_name[8]; /* cache drive name */
+ ulong32 cd_devtype; /* SCSI devicetype */
+ ulong32 cd_ldcnt; /* number of log. drives */
+ ulong32 cd_last_error; /* last error */
+ unchar cd_initialized; /* drive is initialized */
+ unchar cd_removable; /* media is removable */
+ unchar cd_write_protected; /* write protected */
+ unchar cd_flags; /* Pool Hot Fix? */
+ ulong32 ld_blkcnt; /* number of blocks */
+ ulong32 ld_blksize; /* blocksize */
+ ulong32 ld_dcnt; /* number of disks */
+ ulong32 ld_slave; /* log. drive index */
+ ulong32 ld_dtype; /* type of logical drive */
+ ulong32 ld_last_error; /* last error */
+ unchar ld_name[8]; /* log. drive name */
+ unchar ld_error; /* error */
+} PACKED gdth_cdrinfo_str;
+
+/* board features */
+typedef struct {
+ unchar chaining; /* Chaining supported */
+ unchar striping; /* Striping (RAID-0) supp. */
+ unchar mirroring; /* Mirroring (RAID-1) supp. */
+ unchar raid; /* RAID-4/5/10 supported */
+} PACKED gdth_bfeat_str;
+
X /* board info IOCTL */
X typedef struct {
X ulong32 ser_no; /* serial no. */
@@ -351,6 +535,28 @@
X unchar ramparity_pres; /* RAM parity check hardware? */
X } PACKED gdth_binfo_str;
X
+/* get host drive info */
+typedef struct {
+ char name[8]; /* host drive name */
+ ulong32 size; /* size (sectors) */
+ unchar host_drive; /* host drive number */
+ unchar log_drive; /* log. drive (master) */
+ unchar reserved;
+ unchar rw_attribs; /* r/w attribs */
+ ulong32 start_sec; /* start sector */
+} PACKED gdth_hentry_str;
+
+typedef struct {
+ ulong32 entries; /* entry count */
+ ulong32 offset; /* offset of entries */
+ unchar secs_p_head; /* sectors/head */
+ unchar heads_p_cyl; /* heads/cylinder */
+ unchar reserved;
+ unchar clust_drvtype; /* cluster drive type */
+ ulong32 location; /* controller number */
+ gdth_hentry_str entry[MAX_HDRIVES]; /* entries */
+} PACKED gdth_hget_str;
+
X /* scatter/gather element */
X typedef struct {
X ulong32 sg_ptr; /* address */
@@ -642,16 +848,30 @@
X ulong32 info2; /* additional info */
X Scsi_Cmnd *req_first; /* top of request queue */
X struct {
- unchar present; /* host drive present? */
+ unchar present; /* Flag: host drive present? */
+ unchar is_logdrv; /* Flag: logical drive (master)? */
+ unchar is_arraydrv; /* Flag: array drive? */
+ unchar is_master; /* Flag: array drive master? */
+ unchar is_parity; /* Flag: parity drive? */
+ unchar is_hotfix; /* Flag: hotfix drive? */
+ unchar master_no; /* number of master drive */
X unchar lock; /* drive locked? (hot plug) */
X unchar heads; /* mapping */
X unchar secs;
X ushort devtype; /* further information */
X ulong32 size; /* capacity */
- } hdr[MAXID]; /* host drives */
+ unchar ldr_no; /* log. drive no. */
+ unchar rw_attribs; /* r/w attributes */
+ ulong32 start_sec; /* start sector */
+ } hdr[MAX_HDRIVES]; /* host drives */
X struct {
X unchar lock; /* channel locked? (hot plug) */
- } raw[MAXBUS]; /* raw devices */
+ unchar pdev_cnt; /* physical device count */
+ unchar local_no; /* local channel number */
+ unchar io_cnt[MAXID]; /* current IO count */
+ ulong32 address; /* channel address */
+ ulong32 id_list[MAXID]; /* IDs of the phys. devices */
+ } raw[MAXBUS]; /* SCSI channels */
X struct {
X Scsi_Cmnd *cmnd; /* pending request */
X ushort service; /* service */
@@ -659,12 +879,15 @@
X unchar bus_cnt; /* SCSI bus count */
X unchar tid_cnt; /* Target ID count */
X unchar bus_id[MAXBUS]; /* IOP IDs */
+ unchar virt_bus; /* number of virtual bus */
+ unchar more_proc; /* more /proc info supported */
X ushort cmd_cnt; /* command count in DPRAM */
X ushort cmd_len; /* length of actual command */
X ushort cmd_offs_dpmem; /* actual offset in DPRAM */
X ushort ic_all_size; /* sizeof DPRAM interf. area */
X gdth_cpar_str cpar; /* controller cache par. */
- char ctr_name[16]; /* controller name */
+ gdth_bfeat_str bfeat; /* controller features */
+ gdth_binfo_str binfo; /* controller info */
X #if LINUX_VERSION_CODE >= 0x02015F
X spinlock_t smp_lock;
X #endif
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c
--- v2.2.5/linux/drivers/scsi/gdth_proc.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/gdth_proc.c Mon Apr 12 09:56:16 1999
@@ -1,5 +1,5 @@
X /* gdth_proc.c
- * $Id: gdth_proc.c,v 1.11 1998/12/17 15:52:35 achim Exp $
+ * $Id: gdth_proc.c,v 1.13 1999/03/22 16:12:53 achim Exp $
X */
X
X #include "gdth_ioctl.h"
@@ -68,7 +68,6 @@
X static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
X {
X int orig_length, drive, wb_mode;
- char cmnd[12];
X int i, found;
X gdth_ha_str *ha;
X gdth_cmd_str gdtcmd;
@@ -76,7 +75,6 @@
X
X TRACE2(("gdth_set_asc_info() ha %d\n",hanum));
X ha = HADATA(gdth_ctr_tab[hanum]);
- memset(cmnd, 0,10);
X orig_length = length + 5;
X drive = -1;
X wb_mode = 0;
@@ -107,18 +105,7 @@
X gdtcmd.u.cache.DeviceNo = i;
X gdtcmd.u.cache.BlockNo = 1;
X gdtcmd.u.cache.sg_canz = 0;
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 30*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
+ gdth_do_cmd(&scp, &gdtcmd, 30);
X }
X }
X if (!found)
@@ -159,13 +146,9 @@
X }
X
X if (wb_mode) {
- pcpar = (gdth_cpar_str *)kmalloc( sizeof(gdth_cpar_str),
- GFP_ATOMIC | GFP_DMA );
- if (pcpar == NULL) {
- TRACE2(("gdth_set_info(): Unable to allocate memory.\n"));
- printk("Unable to allocate memory.\n");
- return(-EINVAL);
- }
+ if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str)))
+ return(-EBUSY);
+ pcpar = (gdth_cpar_str *)ha->pscratch;
X memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
X gdtcmd.BoardNode = LOCALBOARD;
X gdtcmd.Service = CACHESERVICE;
@@ -175,18 +158,8 @@
X gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
X gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
X pcpar->write_back = wb_mode==1 ? 0:1;
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd, sizeof(gdth_cmd_str),
- gdth_scsi_done, 30*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
- kfree( pcpar );
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ gdth_ioctl_free(hanum);
X printk("Done.\n");
X return(orig_length);
X }
@@ -197,21 +170,23 @@
X
X static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
X {
- char cmnd[12];
X unchar i, j;
X gdth_ha_str *ha;
X gdth_iowr_str *piowr;
X gdth_iord_str *piord;
X gdth_cmd_str *pcmd;
+ gdth_evt_str *pevt;
X ulong32 *ppadd, add_size;
+ ulong32 *ppadd2, add_size2;
X ulong flags;
X
X TRACE2(("gdth_set_bin_info() ha %d\n",hanum));
X ha = HADATA(gdth_ctr_tab[hanum]);
- memset(cmnd, 0,10);
X piowr = (gdth_iowr_str *)buffer;
X piord = NULL;
X pcmd = NULL;
+ ppadd = ppadd2 = NULL;
+ add_size = add_size2 = 0;
X
X if (length < GDTOFFSOF(gdth_iowr_str,iu))
X return(-EINVAL);
@@ -238,6 +213,7 @@
X }
X } else if (piowr->service == SCSIRAWSERVICE) {
X add_size = pcmd->u.raw.sdlen;


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 05'
echo 'File patch-2.2.6 is continued in part 06'
echo 06 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part06

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


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.6 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

+ add_size2 = pcmd->u.raw.sense_len;
X if (ha->raw_feat & SCATTER_GATHER) {
X ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr;
X pcmd->u.raw.sdata = 0xffffffff;
@@ -247,32 +223,26 @@
X ppadd = &pcmd->u.raw.sdata;
X pcmd->u.raw.sg_ranz = 0;
X }
+ ppadd2 = &pcmd->u.raw.sense_data;
X } else {
X return(-EINVAL);
X }
- if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size ))
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2 ))
X return(-EBUSY);
X piord = (gdth_iord_str *)ha->pscratch;
X
- piord->size = sizeof(gdth_iord_str) + add_size;
+ piord->size = sizeof(gdth_iord_str) + add_size + add_size2;
X if (add_size > 0) {
X memcpy(piord->iu.general.data, piowr->iu.general.data, add_size);
X *ppadd = virt_to_bus(piord->iu.general.data);
X }
- /* do IOCTL */


- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();

- scsi_do_cmd(&scp, cmnd, pcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- piowr->timeout*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- piord->status = (ulong32)scp.SCp.Message;
+ if (add_size2 > 0) {
+ memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2);
+ *ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
X }
+ /* do IOCTL */
+ gdth_do_cmd(&scp, pcmd, piowr->timeout);
+ piord->status = (ulong32)scp.SCp.Message;
X break;
X
X case GDTIOCTL_DRVERS:
@@ -381,12 +351,21 @@
X return(-EBUSY);
X piord = (gdth_iord_str *)ha->pscratch;
X if (piowr->iu.event.erase == 0xff) {
- gdth_store_event(ha,
- ((gdth_evt_str *)piowr->iu.event.evt)->event_source,
- ((gdth_evt_str *)piowr->iu.event.evt)->event_idx,
- &((gdth_evt_str *)piowr->iu.event.evt)->event_data);
- if (((gdth_evt_str *)piowr->iu.event.evt)->event_source == ES_ASYNC)
- gdth_log_event(&((gdth_evt_str *)piowr->iu.event.evt)->event_data);
+ pevt = (gdth_evt_str *)piowr->iu.event.evt;
+ if (pevt->event_source == ES_TEST)
+ pevt->event_data.size = sizeof(pevt->event_data.eu.test);
+ else if (pevt->event_source == ES_DRIVER)
+ pevt->event_data.size = sizeof(pevt->event_data.eu.driver);
+ else if (pevt->event_source == ES_SYNC)
+ pevt->event_data.size = sizeof(pevt->event_data.eu.sync);
+ else {
+ pevt->event_data.size = sizeof(pevt->event_data.eu.async);
+ gdth_log_event(&pevt->event_data, NULL);
+ }
+ GDTH_LOCK_HA(ha, flags);
+ gdth_store_event(ha, pevt->event_source, pevt->event_idx,
+ &pevt->event_data);
+ GDTH_UNLOCK_HA(ha, flags);
X } else if (piowr->iu.event.erase == 0xfe) {
X gdth_clear_events();
X } else if (piowr->iu.event.erase == 0) {
@@ -416,28 +395,98 @@
X off_t begin = 0,pos = 0;
X gdth_ha_str *ha;
X gdth_iord_str *piord;
- int id;
+ int id, i, j, k, sec, flag;
+ int no_mdrv = 0, drv_no, is_mirr;
+ ulong32 cnt;
+
+ gdth_cmd_str gdtcmd;
+ gdth_evt_str estr;
+ Scsi_Cmnd scp;
+ Scsi_Device sdev;
+ char hrec[161];
+ struct timeval tv;
+
+ gdth_dskstat_str *pds;
+ gdth_diskinfo_str *pdi;
+ gdth_arrayinf_str *pai;
+ gdth_defcnt_str *pdef;
+ gdth_cdrinfo_str *pcdi;
+ gdth_hget_str *phg;
X
X TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));


X ha = HADATA(gdth_ctr_tab[hanum]);

X id = length;
X
+ memset(&sdev,0,sizeof(Scsi_Device));
+ memset(&scp, 0,sizeof(Scsi_Cmnd));
+ sdev.host = gdth_ctr_vtab[vh];
+ sdev.id = sdev.host->this_id;
+ scp.cmd_len = 12;
+ scp.host = gdth_ctr_vtab[vh];
+ scp.target = sdev.host->this_id;
+ scp.device = &sdev;
+ scp.use_sg = 0;
+
X /* look for buffer ID in length */
X if (id > 1) {
-#if LINUX_VERSION_CODE >= 0x020000
+ /* request is i.e. "cat /proc/scsi/gdth/0" */
+ /* format: %-15s\t%-10s\t%-15s\t%s */
+ /* driver parameters */
+ size = sprintf(buffer+len,"Driver Parameters:\n");
+ len += size; pos = begin + len;
+ if (reserve_list[0] == 0xff)
+ strcpy(hrec, "--");
+ else {
+ sprintf(hrec, "%d", reserve_list[0]);
+ for (i = 1; i < MAX_RES_ARGS; i++) {
+ if (reserve_list[i] == 0xff)
+ break;
+ sprintf(hrec,"%s,%d", hrec, reserve_list[i]);
+ }
+ }
X size = sprintf(buffer+len,
- "%s Disk Array Controller\n",
- ha->ctr_name);
-#else
+ " reserve_mode: \t%d \treserve_list: \t%s\n",
+ reserve_mode, hrec);
+ len += size; pos = begin + len;
X size = sprintf(buffer+len,
- "%s Disk Array Controller (Bus %d)\n",
- ha->ctr_name,busnum);
+ " max_ids: \t%-3d \thdr_channel: \t%d\n",
+ max_ids, hdr_channel);
+ len += size; pos = begin + len;
+
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* controller information */
+ size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
+ len += size; pos = begin + len;
+#if LINUX_VERSION_CODE >= 0x020000
+ strcpy(hrec, ha->binfo.type_string);
+#else
+ sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
X #endif
+ size = sprintf(buffer+len,
+ " Number: \t%d \tName: \t%s\n",
+ hanum, hrec);
X len += size; pos = begin + len;
+
+ if (ha->more_proc)
+ sprintf(hrec, "%d.%02d.%02d-%c%03X",
+ (unchar)(ha->binfo.upd_fw_ver>>24),
+ (unchar)(ha->binfo.upd_fw_ver>>16),
+ (unchar)(ha->binfo.upd_fw_ver),
+ ha->bfeat.raid ? 'R':'N',
+ ha->binfo.upd_revision);
+ else
+ sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8),
+ (unchar)(ha->cpar.version));
+
X size = sprintf(buffer+len,
- "Firmware Version: %d.%2d\tDriver Version: %s\n",
- (unchar)(ha->cpar.version>>8),
- (unchar)(ha->cpar.version),GDTH_VERSION_STR);
+ " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
+ GDTH_VERSION_STR, hrec);
X len += size; pos = begin + len;
X
X if (pos < offset) {
@@ -447,7 +496,412 @@
X if (pos > offset + length)
X goto stop_output;
X
+ if (ha->more_proc) {
+ /* more information: 1. about controller */
+ size = sprintf(buffer+len,
+ " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
+ ha->binfo.ser_no, ha->binfo.memsize / 1024);
+ len += size; pos = begin + len;
+
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 2. about physical devices */
+ size = sprintf(buffer+len,"\nPhysical Devices:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < ha->bus_cnt; ++i) {
+ /* 2.a statistics (and retries/reassigns) */
+ TRACE2(("pdr_statistics() chn %d\n",i));
+ pds = (gdth_dskstat_str *)(ha->pscratch + GDTH_SCRATCH/4);
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
+ gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
+ gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
+ pds->bid = ha->raw[i].local_no;
+ pds->first = 0;
+ pds->entries = ha->raw[i].pdev_cnt;
+ cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) /
+ sizeof(pds->list[0]);
+ if (pds->entries > cnt)
+ pds->entries = cnt;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message != S_OK)
+ pds->count = 0;
+ TRACE2(("pdr_statistics() entries %d status %d\n",
+ pds->count, scp.SCp.Message));
+
+ /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
+ for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
+ /* 2.b drive info */
+ TRACE2(("scsi_drv_info() chn %d dev %d\n",
+ i, ha->raw[i].id_list[j]));
+ pdi = (gdth_diskinfo_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
+ gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel =
+ ha->raw[i].address | ha->raw[i].id_list[j];
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message == S_OK) {
+ strncpy(hrec,pdi->vendor,8);
+ strncpy(hrec+8,pdi->product,16);
+ strncpy(hrec+24,pdi->revision,4);
+ hrec[28] = 0;
+ size = sprintf(buffer+len,
+ "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
+ 'A'+i,pdi->target_id,pdi->lun,hrec);
+ len += size; pos = begin + len;
+ flag = TRUE;
+ pdi->no_ldrive &= 0xffff;
+ if (pdi->no_ldrive == 0xffff)
+ strcpy(hrec,"--");
+ else
+ sprintf(hrec,"%d",pdi->no_ldrive);
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
+ pdi->blkcnt/(1024*1024/pdi->blksize),
+ hrec);
+ len += size; pos = begin + len;
+ } else {
+ pdi->devtype = 0xff;
+ }
+
+ if (pdi->devtype == 0) {
+ /* search retries/reassigns */
+ for (k = 0; k < pds->count; ++k) {
+ if (pds->list[k].tid == pdi->target_id &&
+ pds->list[k].lun == pdi->lun) {
+ size = sprintf(buffer+len,
+ " Retries: \t%-6d \tReassigns: \t%d\n",
+ pds->list[k].retries,
+ pds->list[k].reassigns);
+ len += size; pos = begin + len;
+ break;
+ }
+ }
+ /* 2.c grown defects */
+ TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
+ i, ha->raw[i].id_list[j]));
+ pdef = (gdth_defcnt_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
+ gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel =
+ ha->raw[i].address | ha->raw[i].id_list[j];
+ pdef->sddc_type = 0x08;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message == S_OK) {
+ size = sprintf(buffer+len,
+ " Grown Defects:\t%d\n",
+ pdef->sddc_cnt);
+ len += size; pos = begin + len;
+ }
+ }
+ }
+ }
+ gdth_ioctl_free(hanum);
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 3. about logical drives */
+ size = sprintf(buffer+len,"\nLogical Drives:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!ha->hdr[i].is_logdrv)
+ continue;
+ drv_no = i;
+ j = k = 0;
+ is_mirr = FALSE;
+ do {
+ /* 3.a log. drive info */
+ TRACE2(("cache_drv_info() drive no %d\n",drv_no));
+ pcdi = (gdth_cdrinfo_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
+ gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
+ gdtcmd.u.ioctl.channel = drv_no;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message != S_OK)
+ break;
+ pcdi->ld_dtype >>= 16;
+ j++;
+ if (pcdi->ld_dtype > 2) {
+ strcpy(hrec, "missing");
+ } else if (pcdi->ld_error & 1) {
+ strcpy(hrec, "fault");
+ } else if (pcdi->ld_error & 2) {
+ strcpy(hrec, "invalid");
+ k++; j--;
+ } else {
+ strcpy(hrec, "ok");
+ }
+
+ if (drv_no == i) {
+ size = sprintf(buffer+len,
+ "\n Number: \t%-2d \tStatus: \t%s\n",
+ drv_no, hrec);
+ len += size; pos = begin + len;
+ flag = TRUE;
+ no_mdrv = pcdi->cd_ldcnt;
+ if (no_mdrv > 1 || pcdi->ld_slave != -1) {
+ is_mirr = TRUE;
+ strcpy(hrec, "RAID-1");
+ } else if (pcdi->ld_dtype == 0) {
+ strcpy(hrec, "Disk");
+ } else if (pcdi->ld_dtype == 1) {
+ strcpy(hrec, "RAID-0");
+ } else if (pcdi->ld_dtype == 2) {
+ strcpy(hrec, "Chain");
+ } else {
+ strcpy(hrec, "???");
+ }
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tType: \t%s\n",
+ pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
+ hrec);
+ len += size; pos = begin + len;
+ } else {
+ size = sprintf(buffer+len,
+ " Slave Number: \t%-2d \tStatus: \t%s\n",
+ drv_no & 0x7fff, hrec);
+ len += size; pos = begin + len;
+ }
+ drv_no = pcdi->ld_slave;
+ } while (drv_no != -1);
+
+ if (is_mirr) {
+ size = sprintf(buffer+len,
+ " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
+ no_mdrv - j - k, k);
+ len += size; pos = begin + len;
+ }
+
+ if (!ha->hdr[i].is_arraydrv)
+ strcpy(hrec, "--");
+ else
+ sprintf(hrec, "%d", ha->hdr[i].master_no);
+ size = sprintf(buffer+len,
+ " To Array Drv.:\t%s\n", hrec);
+ len += size; pos = begin + len;
+ }
+ gdth_ioctl_free(hanum);
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 4. about array drives */
+ size = sprintf(buffer+len,"\nArray Drives:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
+ continue;
+ /* 4.a array drive info */
+ TRACE2(("array_info() drive no %d\n",i));
+ pai = (gdth_arrayinf_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
+ gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel = i;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message == S_OK) {
+ if (pai->ai_state == 0)
+ strcpy(hrec, "idle");
+ else if (pai->ai_state == 2)
+ strcpy(hrec, "build");
+ else if (pai->ai_state == 4)
+ strcpy(hrec, "ready");
+ else if (pai->ai_state == 6)
+ strcpy(hrec, "fail");
+ else if (pai->ai_state == 8 || pai->ai_state == 10)
+ strcpy(hrec, "rebuild");
+ else
+ strcpy(hrec, "error");
+ if (pai->ai_ext_state & 0x10)
+ strcat(hrec, "/expand");
+ else if (pai->ai_ext_state & 0x1)
+ strcat(hrec, "/patch");
+ size = sprintf(buffer+len,
+ "\n Number: \t%-2d \tStatus: \t%s\n",
+ i,hrec);
+ len += size; pos = begin + len;
+ flag = TRUE;
+
+ if (pai->ai_type == 0)
+ strcpy(hrec, "RAID-0");
+ else if (pai->ai_type == 4)
+ strcpy(hrec, "RAID-4");
+ else if (pai->ai_type == 5)
+ strcpy(hrec, "RAID-5");
+ else
+ strcpy(hrec, "RAID-10");
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tType: \t%s\n",
+ pai->ai_size/(1024*1024/pai->ai_secsize),
+ hrec);
+ len += size; pos = begin + len;
+ }
+ }
+ gdth_ioctl_free(hanum);
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 5. about host drives */
+ size = sprintf(buffer+len,"\nHost Drives:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!ha->hdr[i].is_logdrv ||
+ (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
+ continue;
+ /* 5.a get host drive list */
+ TRACE2(("host_get() drv_no %d\n",i));
+ phg = (gdth_hget_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
+ gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel = i;
+ phg->entries = MAX_HDRIVES;
+ phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message != S_OK) {
+ ha->hdr[i].ldr_no = i;
+ ha->hdr[i].rw_attribs = 0;
+ ha->hdr[i].start_sec = 0;
+ } else {
+ for (j = 0; j < phg->entries; ++j) {
+ k = phg->entry[j].host_drive;
+ if (k >= MAX_HDRIVES)
+ continue;
+ ha->hdr[k].ldr_no = phg->entry[j].log_drive;
+ ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
+ ha->hdr[k].start_sec = phg->entry[j].start_sec;
+ }
+ }
+ TRACE2(("host_get entries %d status %d\n",
+ phg->entries, scp.SCp.Message));
+ }
+ gdth_ioctl_free(hanum);
+
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!(ha->hdr[i].present))
+ continue;
+
+ size = sprintf(buffer+len,
+ "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
+ i, ha->hdr[i].ldr_no);
+ len += size; pos = begin + len;
+ flag = TRUE;
+
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
+ ha->hdr[i].size/2048, ha->hdr[i].start_sec);
+ len += size; pos = begin + len;
+ }
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+ }
+
+ /* controller events */
+ size = sprintf(buffer+len,"\nController Events:\n");
+ len += size; pos = begin + len;
+
+ for (id = -1;;) {
+ id = gdth_read_event(ha, id, &estr);
+ if (estr.event_source == 0)
+ break;
+ if (estr.event_data.eu.driver.ionode == hanum &&
+ estr.event_source == ES_ASYNC) {
+ gdth_log_event(&estr.event_data, hrec);
+ do_gettimeofday(&tv);
+ sec = (int)(tv.tv_sec - estr.first_stamp);
+ if (sec < 0) sec = 0;
+ size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
+ sec/3600, sec%3600/60, sec%60, hrec);
+ len += size; pos = begin + len;
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+ }
+ if (id == -1)
+ break;
+ }
X } else {
+ /* request from tool (GDTMON,..) */
X piord = (gdth_iord_str *)ha->pscratch;
X if (piord == NULL)
X goto stop_output;
@@ -474,6 +928,22 @@
X return(len);
X }
X
+static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *gdtcmd,int timeout)
+{
+ char cmnd[12];
+ struct semaphore sem = MUTEX_LOCKED;
+
+ TRACE2(("gdth_do_cmd()\n"));
+ memset(cmnd, 0, 12);
+ scp->request.rq_status = RQ_SCSI_BUSY;
+ scp->request.sem = &sem;
+ scp->SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
+ scsi_do_cmd(scp, cmnd, gdtcmd, sizeof(gdth_cmd_str),
+ gdth_scsi_done, timeout*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
+ down(&sem);
+}
X
X void gdth_scsi_done(Scsi_Cmnd *scp)
X {
@@ -492,7 +962,7 @@
X int ret_val;
X
X if (size == 0 || size > GDTH_SCRATCH)
- return -1;
+ return FALSE;
X

X ha = HADATA(gdth_ctr_tab[hanum]);

X GDTH_LOCK_HA(ha, flags);
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/gdth_proc.h linux/drivers/scsi/gdth_proc.h
--- v2.2.5/linux/drivers/scsi/gdth_proc.h Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/gdth_proc.h Mon Apr 12 09:56:16 1999
@@ -2,7 +2,7 @@
X #define _GDTH_PROC_H
X
X /* gdth_proc.h
- * $Id: gdth_proc.h,v 1.5 1998/12/17 15:43:53 achim Exp $
+ * $Id: gdth_proc.h,v 1.6 1999/03/05 14:32:36 achim Exp $
X */
X
X static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
@@ -18,6 +18,7 @@
X static void gdth_start_timeout(int hanum, int busnum, int id);
X static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
X
+static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *cmd,int timeout);
X void gdth_scsi_done(Scsi_Cmnd *scp);
X
X #endif
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.2.5/linux/drivers/scsi/hosts.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/hosts.c Mon Apr 12 09:51:04 1999
@@ -195,6 +195,10 @@
X #include "53c7,8xx.h"
X #endif
X
+#ifdef CONFIG_SCSI_SYM53C8XX
+#include "sym53c8xx.h"
+#endif
+
X #ifdef CONFIG_SCSI_NCR53C8XX
X #include "ncr53c8xx.h"
X #endif
@@ -501,6 +505,9 @@
X #endif
X #ifdef CONFIG_SCSI_NCR53C7xx
X NCR53c7xx,
+#endif
+#ifdef CONFIG_SCSI_SYM53C8XX
+ SYM53C8XX,
X #endif
X #ifdef CONFIG_SCSI_NCR53C8XX
X NCR53C8XX,
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.2.5/linux/drivers/scsi/megaraid.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/megaraid.c Fri Apr 16 11:49:00 1999
@@ -114,7 +114,6 @@
X #include <linux/sched.h>
X #include <linux/stat.h>
X #include <linux/malloc.h> /* for kmalloc() */
-#include <linux/config.h> /* for CONFIG_PCI */
X #if LINUX_VERSION_CODE < 0x20100
X #include <linux/bios32.h>
X #else
@@ -884,7 +883,7 @@
X
X spin_lock_irqsave(&mega_lock,flags);
X
-#if !MULTI_IO
+#ifndef CONFIG_MEGARAID_MULTI_IO
X if (megaCfg->flag & PENDING) {
X spin_unlock_irqrestore(&mega_lock,flags);
X return -1;
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.2.5/linux/drivers/scsi/megaraid.h Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/megaraid.h Fri Apr 16 14:28:51 1999
@@ -5,9 +5,6 @@
X #include <linux/version.h>
X #endif
X
-#define MULTI_IO 0 /* change to 1 for fully parallel I/O to adapter */
- /* works on some systems, not on others yet */
-
X #define IN_ISR 0x80000000L
X #define NO_INTR 0x40000000L
X #define IN_TIMEOUT 0x20000000L
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.2.5/linux/drivers/scsi/ncr53c8xx.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/ncr53c8xx.c Mon Apr 12 09:51:04 1999
@@ -73,7 +73,7 @@
X */
X
X /*
-** March 6 1999, version 3.1h
+** March 7 1999, version 3.2
X **
X ** Supported SCSI-II features:
X ** Synchronous negotiation
@@ -98,6 +98,11 @@
X ** Shared IRQ (since linux-1.3.72)
X */
X
+/*
+** Name and version of the driver
+*/
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2"
+
X #define SCSI_NCR_DEBUG_FLAGS (0)
X
X /*==========================================================
@@ -717,12 +722,12 @@
X ** /proc directory entry and proc_info function
X */
X
-struct proc_dir_entry proc_scsi_ncr53c8xx = {
+static struct proc_dir_entry proc_scsi_ncr53c8xx = {
X PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx",
X S_IFDIR | S_IRUGO | S_IXUGO, 2
X };
X #ifdef SCSI_NCR_PROC_INFO_SUPPORT
-int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
+static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
X int length, int hostno, int func);
X #endif
X
@@ -732,6 +737,7 @@
X ** This structure is initialized from linux config options.
X ** It can be overridden at boot-up by the boot command line.
X */
+#define SCSI_NCR_MAX_EXCLUDES 8
X struct ncr_driver_setup {
X u_char master_parity;
X u_char scsi_parity;
@@ -753,6 +759,9 @@
X u_char diff_support;
X u_char irqm;
X u_char bus_check;
+ u_char optimize;
+ u_char recovery;
+ u_int excludes[SCSI_NCR_MAX_EXCLUDES];
X char tag_ctrl[100];
X };
X
@@ -4672,7 +4681,11 @@
X
X if (request_irq(device->slot.irq, ncr53c8xx_intr,
X ((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) |
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
X ((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT),
+#else
+ 0,
+#endif
X "ncr53c8xx", np)) {
X #ifdef __sparc__
X printk(KERN_ERR "%s: request irq %s failure\n",
@@ -4831,7 +4844,7 @@
X **
X **==========================================================
X */
-int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
+static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
X {
X /* Scsi_Device *device = cmd->device; */
X tcb_p tp = &np->target[cmd->target];
@@ -5395,7 +5408,7 @@
X **
X **==========================================================
X */
-int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset)
+static int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset)
X {
X /* Scsi_Device *device = cmd->device; */
X ccb_p cp;
@@ -5965,7 +5978,7 @@
X ** This CCB has been skipped by the NCR.
X ** Queue it in the correponding unit queue.
X */
-void ncr_ccb_skipped(ncb_p np, ccb_p cp)
+static void ncr_ccb_skipped(ncb_p np, ccb_p cp)
X {
X tcb_p tp = &np->target[cp->target];
X lcb_p lp = tp->lp[cp->lun];
@@ -9235,6 +9248,7 @@
X int val;
X int base;
X int c;
+ int xi = 0;
X
X while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
X char *pe;
@@ -9306,6 +9320,10 @@
X
X else if (!strncmp(cur, "safe:", 5) && val)
X memcpy(&driver_setup, &driver_safe_setup, sizeof(driver_setup));
+ else if (!strncmp(cur, "excl:", 5)) {
+ if (xi < SCSI_NCR_MAX_EXCLUDES)
+ driver_setup.excludes[xi++] = val;
+ }
X else
X printk("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
X
@@ -9684,6 +9702,14 @@
X &latency_timer);
X
X /*
+ ** If user excludes this chip, donnot initialize it.
+ */
+ for (i = 0 ; i < SCSI_NCR_MAX_EXCLUDES ; i++) {
+ if (driver_setup.excludes[i] ==
+ (io_port & PCI_BASE_ADDRESS_IO_MASK))
+ return -1;
+ }
+ /*
X * Check if the chip is supported
X */
X chip = 0;
@@ -10169,6 +10195,14 @@
X }
X
X /*
+** Linux entry point for info() function
+*/
+const char *ncr53c8xx_info (struct Scsi_Host *host)
+{
+ return SCSI_NCR_DRIVER_NAME;
+}
+
+/*
X ** Linux entry point of queuecommand() function
X */
X
@@ -10792,7 +10826,7 @@
X ** - func = 1 means write (parse user control command)
X */
X
-int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
+static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
X int length, int hostno, int func)
X {
X struct Scsi_Host *host;
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.2.5/linux/drivers/scsi/ncr53c8xx.h Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/ncr53c8xx.h Fri Apr 16 14:28:59 1999
@@ -42,214 +42,7 @@
X #ifndef NCR53C8XX_H
X #define NCR53C8XX_H
X
-/*
-** Name and revision of the driver
-*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1h"
-
-/*
-** Check supported Linux versions
-*/
-
-#if !defined(LINUX_VERSION_CODE)
-#include <linux/version.h>
-#endif
-#include <linux/config.h>
-
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
-/*
- * No more an option, enabled by default.
- */
-#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#endif
-
-/*
-** These options are not tunable from 'make config'
-*/
-#define SCSI_NCR_PROC_INFO_SUPPORT
-
-/*
-** If you want a driver as small as possible, donnot define the
-** following options.
-*/
-#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-#define SCSI_NCR_DEBUG_INFO_SUPPORT
-#define SCSI_NCR_PCI_FIX_UP_SUPPORT
-#ifdef SCSI_NCR_PROC_INFO_SUPPORT
-# ifdef CONFIG_SCSI_NCR53C8XX_PROFILE
-# define SCSI_NCR_PROFILE_SUPPORT
-# endif
-# define SCSI_NCR_USER_COMMAND_SUPPORT
-# define SCSI_NCR_USER_INFO_SUPPORT
-#endif
-
-/*==========================================================
-**
-** nvram settings - #define SCSI_NCR_NVRAM_SUPPORT to enable
-**
-**==========================================================
-*/
-
-#ifdef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#define SCSI_NCR_NVRAM_SUPPORT
-/* #define SCSI_NCR_DEBUG_NVRAM */
-#endif
-
-/* ---------------------------------------------------------------------
-** Take into account kernel configured parameters.
-** Most of these options can be overridden at startup by a command line.
-** ---------------------------------------------------------------------
-*/
-
-/*
- * For Ultra2 SCSI support option, use special features and allow 40Mhz
- * synchronous data transfers.
- */
-#define SCSI_NCR_SETUP_SPECIAL_FEATURES (3)
-#define SCSI_NCR_SETUP_ULTRA_SCSI (2)
-#define SCSI_NCR_MAX_SYNC (40)
-
-/*
- * Allow tags from 2 to 64, default 8
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#if CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
-#define SCSI_NCR_MAX_TAGS (2)
-#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 64
-#define SCSI_NCR_MAX_TAGS (64)
-#else
-#define SCSI_NCR_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#endif
-#else
-#define SCSI_NCR_MAX_TAGS (8)
-#endif
-
-/*
- * Allow tagged command queuing support if configured with default number
- * of tags set to max (see above).
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#define SCSI_NCR_SETUP_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#elif defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
-#define SCSI_NCR_SETUP_DEFAULT_TAGS SCSI_NCR_MAX_TAGS
-#else
-#define SCSI_NCR_SETUP_DEFAULT_TAGS (0)
-#endif
-
-/*
- * Use normal IO if configured. Forced for alpha and ppc.
- */
-#if defined(CONFIG_SCSI_NCR53C8XX_IOMAPPED)
-#define SCSI_NCR_IOMAPPED
-#elif defined(__alpha__) || defined(__powerpc__)
-#define SCSI_NCR_IOMAPPED
-#elif defined(__sparc__)
-#undef SCSI_NCR_IOMAPPED
-#endif
-
-/*
- * Sync transfer frequency at startup.
- * Allow from 5Mhz to 40Mhz default 20 Mhz.
- */
-#ifndef CONFIG_SCSI_NCR53C8XX_SYNC
-#define CONFIG_SCSI_NCR53C8XX_SYNC (20)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
-#undef CONFIG_SCSI_NCR53C8XX_SYNC
-#define CONFIG_SCSI_NCR53C8XX_SYNC SCSI_NCR_MAX_SYNC
-#endif
-
-#if CONFIG_SCSI_NCR53C8XX_SYNC == 0
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (255)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 5
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (50)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 20
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC))
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (11)
-#else
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (10)
-#endif
-
-/*
- * Disallow disconnections at boot-up
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
-#define SCSI_NCR_SETUP_DISCONNECTION (0)
-#else
-#define SCSI_NCR_SETUP_DISCONNECTION (1)
-#endif
-
-/*
- * Force synchronous negotiation for all targets
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (1)
-#else
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (0)
-#endif
-
-/*
- * Disable master parity checking (flawed hardwares need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
-#define SCSI_NCR_SETUP_MASTER_PARITY (0)
-#else
-#define SCSI_NCR_SETUP_MASTER_PARITY (1)
-#endif
-
-/*
- * Disable scsi parity checking (flawed devices may need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
-#define SCSI_NCR_SETUP_SCSI_PARITY (0)
-#else
-#define SCSI_NCR_SETUP_SCSI_PARITY (1)
-#endif
-
-/*
- * Vendor specific stuff
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
-#define SCSI_NCR_SETUP_LED_PIN (1)
-#define SCSI_NCR_SETUP_DIFF_SUPPORT (3)
-#else
-#define SCSI_NCR_SETUP_LED_PIN (0)
-#define SCSI_NCR_SETUP_DIFF_SUPPORT (0)
-#endif
-
-/*
- * Settle time after reset at boot-up
- */
-#define SCSI_NCR_SETUP_SETTLE_TIME (2)
-
-/*
-** Other parameters not configurable with "make config"
-** Avoid to change these constants, unless you know what you are doing.
-*/
-
-#define SCSI_NCR_ALWAYS_SIMPLE_TAG
-#define SCSI_NCR_MAX_SCATTER (127)
-#define SCSI_NCR_MAX_TARGET (16)
-
-/* No need to use a too large adapter queue */
-#if SCSI_NCR_MAX_TAGS <= 32
-#define SCSI_NCR_CAN_QUEUE (7*SCSI_NCR_MAX_TAGS)
-#else
-#define SCSI_NCR_CAN_QUEUE (250)
-#endif
-
-#define SCSI_NCR_CMD_PER_LUN (SCSI_NCR_MAX_TAGS)
-#define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER)
-
-#define SCSI_NCR_TIMER_INTERVAL (HZ)
-
-#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
-#define SCSI_NCR_MAX_LUN (8)
-#else
-#define SCSI_NCR_MAX_LUN (1)
-#endif
+#include "sym53c8xx_defs.h"
X
X /*
X ** Define Scsi_Host_Template parameters
@@ -263,6 +56,7 @@
X
X int ncr53c8xx_abort(Scsi_Cmnd *);
X int ncr53c8xx_detect(Scsi_Host_Template *tpnt);
+const char *ncr53c8xx_info(struct Scsi_Host *host);
X int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
X int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int);
X
@@ -272,11 +66,13 @@
X #define ncr53c8xx_release NULL
X #endif
X
+
X #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
X
-#define NCR53C8XX { name: SCSI_NCR_DRIVER_NAME, \
+#define NCR53C8XX { name: "", \
X detect: ncr53c8xx_detect, \
X release: ncr53c8xx_release, \
+ info: ncr53c8xx_info, \
X queuecommand: ncr53c8xx_queue_command,\
X abort: ncr53c8xx_abort, \
X reset: ncr53c8xx_reset, \
@@ -290,8 +86,8 @@
X #else
X
X #define NCR53C8XX { NULL, NULL, NULL, NULL, \
- SCSI_NCR_DRIVER_NAME, ncr53c8xx_detect, \
- ncr53c8xx_release, NULL, NULL, \
+ NULL, ncr53c8xx_detect, \
+ ncr53c8xx_release, ncr53c8xx_info, NULL, \
X ncr53c8xx_queue_command,ncr53c8xx_abort, \
X ncr53c8xx_reset, NULL, scsicam_bios_param, \
X SCSI_NCR_CAN_QUEUE, 7, \
@@ -302,867 +98,4 @@
X
X #endif /* defined(HOSTS_C) || defined(MODULE) */
X
-#ifndef HOSTS_C
-
-/*
-** IO functions definition for big/little endian support.
-** For now, the NCR is only supported in little endian addressing mode,
-** and big endian byte ordering is only supported for the PPC.
-** MMIO is not used on PPC.
-*/
-
-#ifdef __BIG_ENDIAN
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
-#error "BIG ENDIAN byte ordering needs kernel version >= 2.1.0"
-#endif
-
-#if defined(__powerpc__)
-#define inw_l2b inw
-#define inl_l2b inl
-#define outw_b2l outw
-#define outl_b2l outl
-#elif defined(__sparc__)
-#define readw_l2b readw
-#define readl_l2b readl
-#define writew_b2l writew
-#define writel_b2l writel
-#else
-#error "Support for BIG ENDIAN is only available for PowerPC and SPARC"
-#endif
-
-#else /* Assumed x86 or alpha */
-
-#define inw_raw inw
-#define inl_raw inl
-#define outw_raw outw
-#define outl_raw outl
-#define readw_raw readw
-#define readl_raw readl
-#define writew_raw writew
-#define writel_raw writel
-
-#endif
-
-#ifdef SCSI_NCR_BIG_ENDIAN
-#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
-#endif
-
-/*
-** NCR53C8XX Device Ids
-*/
-
-#ifndef PCI_DEVICE_ID_NCR_53C810
-#define PCI_DEVICE_ID_NCR_53C810 1
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C810AP
-#define PCI_DEVICE_ID_NCR_53C810AP 5
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C815
-#define PCI_DEVICE_ID_NCR_53C815 4
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C820
-#define PCI_DEVICE_ID_NCR_53C820 2
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C825
-#define PCI_DEVICE_ID_NCR_53C825 3
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C860
-#define PCI_DEVICE_ID_NCR_53C860 6
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C875
-#define PCI_DEVICE_ID_NCR_53C875 0xf
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C875J
-#define PCI_DEVICE_ID_NCR_53C875J 0x8f
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C885
-#define PCI_DEVICE_ID_NCR_53C885 0xd
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C895
-#define PCI_DEVICE_ID_NCR_53C895 0xc
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C896
-#define PCI_DEVICE_ID_NCR_53C896 0xb
-#endif
-
-/*
-** NCR53C8XX devices features table.
-*/
-typedef struct {
- unsigned short device_id;
- unsigned short revision_id;
- char *name;
- unsigned char burst_max;
- unsigned char offset_max;
- unsigned char nr_divisor;
- unsigned int features;
-#define FE_LED0 (1<<0)
-#define FE_WIDE (1<<1)
-#define FE_ULTRA (1<<2)
-#define FE_ULTRA2 (1<<3)
-#define FE_DBLR (1<<4)
-#define FE_QUAD (1<<5)
-#define FE_ERL (1<<6)
-#define FE_CLSE (1<<7)
-#define FE_WRIE (1<<8)
-#define FE_ERMP (1<<9)
-#define FE_BOF (1<<10)
-#define FE_DFS (1<<11)
-#define FE_PFEN (1<<12)
-#define FE_LDSTR (1<<13)
-#define FE_RAM (1<<14)
-#define FE_CLK80 (1<<15)
-#define FE_RAM8K (1<<16)
-#define FE_64BIT (1<<17)
-#define FE_IO256 (1<<18)
-#define FE_NOPM (1<<19)
-#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
-#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80)
-#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
-} ncr_chip;
-
-/*
-** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 3.
-** Memory Read transaction terminated by a retry followed by
-** Memory Read Line command.
-*/
-#define FE_CACHE0_SET (FE_CACHE_SET & ~FE_ERL)
-
-/*
-** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 5.
-** On paper, this errata is harmless. But it is a good reason for
-** using a shorter programmed burst length (64 DWORDS instead of 128).
-*/
-
-#define SCSI_NCR_CHIP_TABLE \
-{ \
- {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, \
- FE_ERL} \
- , \
- {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, \
- FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF} \
- , \
- {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4, 8, 4, \
- FE_ERL|FE_BOF} \
- , \
- {PCI_DEVICE_ID_NCR_53C820, 0xff, "820", 4, 8, 4, \
- FE_WIDE|FE_ERL} \
- , \
- {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 4, 8, 4, \
- FE_WIDE|FE_ERL|FE_BOF} \
- , \
- {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6, 8, 4, \
- FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} \
- , \
- {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, \
- FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN} \
- , \
- {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C875, 0x0f, "875", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C875, 0xff, "876", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C875J,0xff, "875J", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 7, 31, 7, \
- FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 7, 31, 7, \
- FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\
- FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM}\
-}
-
-/*
- * List of supported NCR chip ids
- */
-#define SCSI_NCR_CHIP_IDS \
-{ \
- PCI_DEVICE_ID_NCR_53C810, \
- PCI_DEVICE_ID_NCR_53C815, \
- PCI_DEVICE_ID_NCR_53C820, \
- PCI_DEVICE_ID_NCR_53C825, \
- PCI_DEVICE_ID_NCR_53C860, \
- PCI_DEVICE_ID_NCR_53C875, \
- PCI_DEVICE_ID_NCR_53C875J, \
- PCI_DEVICE_ID_NCR_53C885, \
- PCI_DEVICE_ID_NCR_53C895, \
- PCI_DEVICE_ID_NCR_53C896 \
-}
-
-/*
-** Initial setup.
-** Can be overriden at startup by a command line.
-*/
-#define SCSI_NCR_DRIVER_SETUP \
-{ \
- SCSI_NCR_SETUP_MASTER_PARITY, \
- SCSI_NCR_SETUP_SCSI_PARITY, \
- SCSI_NCR_SETUP_DISCONNECTION, \
- SCSI_NCR_SETUP_SPECIAL_FEATURES, \
- SCSI_NCR_SETUP_ULTRA_SCSI, \
- SCSI_NCR_SETUP_FORCE_SYNC_NEGO, \
- 0, \
- 0, \
- 1, \
- 1, \
- SCSI_NCR_SETUP_DEFAULT_TAGS, \
- SCSI_NCR_SETUP_DEFAULT_SYNC, \
- 0x00, \
- 7, \
- SCSI_NCR_SETUP_LED_PIN, \
- 1, \
- SCSI_NCR_SETUP_SETTLE_TIME, \
- SCSI_NCR_SETUP_DIFF_SUPPORT, \
- 0, \
- 1 \
-}
-
-/*
-** Boot fail safe setup.
-** Override initial setup from boot command line:
-** ncr53c8xx=safe:y
-*/
-#define SCSI_NCR_DRIVER_SAFE_SETUP \
-{ \
- 0, \
- 1, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 1, \
- 2, \
- 0, \
- 255, \
- 0x00, \
- 255, \
- 0, \
- 0, \
- 10, \
- 1, \
- 1, \
- 1 \
-}
-
-/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
-
-/*-----------------------------------------------------------------
-**
-** The ncr 53c810 register structure.
-**
-**-----------------------------------------------------------------
-*/
-
-struct ncr_reg {
-/*00*/ u_char nc_scntl0; /* full arb., ena parity, par->ATN */
-
-/*01*/ u_char nc_scntl1; /* no reset */
- #define ISCON 0x10 /* connected to scsi */
- #define CRST 0x08 /* force reset */
-
-/*02*/ u_char nc_scntl2; /* no disconnect expected */
- #define SDU 0x80 /* cmd: disconnect will raise error */
- #define CHM 0x40 /* sta: chained mode */
- #define WSS 0x08 /* sta: wide scsi send [W]*/
- #define WSR 0x01 /* sta: wide scsi received [W]*/
-
-/*03*/ u_char nc_scntl3; /* cnf system clock dependent */
- #define EWS 0x08 /* cmd: enable wide scsi [W]*/
- #define ULTRA 0x80 /* cmd: ULTRA enable */
-
-/*04*/ u_char nc_scid; /* cnf host adapter scsi address */
- #define RRE 0x40 /* r/w:e enable response to resel. */
- #define SRE 0x20 /* r/w:e enable response to select */
-
-/*05*/ u_char nc_sxfer; /* ### Sync speed and count */
-
-/*06*/ u_char nc_sdid; /* ### Destination-ID */
-
-/*07*/ u_char nc_gpreg; /* ??? IO-Pins */
-
-/*08*/ u_char nc_sfbr; /* ### First byte in phase */
-
-/*09*/ u_char nc_socl;
- #define CREQ 0x80 /* r/w: SCSI-REQ */
- #define CACK 0x40 /* r/w: SCSI-ACK */
- #define CBSY 0x20 /* r/w: SCSI-BSY */
- #define CSEL 0x10 /* r/w: SCSI-SEL */
- #define CATN 0x08 /* r/w: SCSI-ATN */
- #define CMSG 0x04 /* r/w: SCSI-MSG */
- #define CC_D 0x02 /* r/w: SCSI-C_D */
- #define CI_O 0x01 /* r/w: SCSI-I_O */
-
-/*0a*/ u_char nc_ssid;
-
-/*0b*/ u_char nc_sbcl;
-
-/*0c*/ u_char nc_dstat;
- #define DFE 0x80 /* sta: dma fifo empty */
- #define MDPE 0x40 /* int: master data parity error */
- #define BF 0x20 /* int: script: bus fault */
- #define ABRT 0x10 /* int: script: command aborted */
- #define SSI 0x08 /* int: script: single step */
- #define SIR 0x04 /* int: script: interrupt instruct. */
- #define IID 0x01 /* int: script: illegal instruct. */
-
-/*0d*/ u_char nc_sstat0;
- #define ILF 0x80 /* sta: data in SIDL register lsb */
- #define ORF 0x40 /* sta: data in SODR register lsb */
- #define OLF 0x20 /* sta: data in SODL register lsb */
- #define AIP 0x10 /* sta: arbitration in progress */
- #define LOA 0x08 /* sta: arbitration lost */
- #define WOA 0x04 /* sta: arbitration won */
- #define IRST 0x02 /* sta: scsi reset signal */
- #define SDP 0x01 /* sta: scsi parity signal */
-
-/*0e*/ u_char nc_sstat1;
- #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
-
-/*0f*/ u_char nc_sstat2;
- #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
- #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
- #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
- #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
- #define LDSC 0x02 /* sta: disconnect & reconnect */
-
-/*10*/ u_int32 nc_dsa; /* --> Base page */
-
-/*14*/ u_char nc_istat; /* --> Main Command and status */
- #define CABRT 0x80 /* cmd: abort current operation */
- #define SRST 0x40 /* mod: reset chip */
- #define SIGP 0x20 /* r/w: message from host to ncr */
- #define SEM 0x10 /* r/w: message between host + ncr */
- #define CON 0x08 /* sta: connected to scsi */
- #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
- #define SIP 0x02 /* sta: scsi-interrupt */
- #define DIP 0x01 /* sta: host/script interrupt */
-
-/*15*/ u_char nc_15_;
-/*16*/ u_char nc_16_;
-/*17*/ u_char nc_17_;
-
-/*18*/ u_char nc_ctest0;
-/*19*/ u_char nc_ctest1;
-
-/*1a*/ u_char nc_ctest2;
- #define CSIGP 0x40
-
-/*1b*/ u_char nc_ctest3;
- #define FLF 0x08 /* cmd: flush dma fifo */
- #define CLF 0x04 /* cmd: clear dma fifo */
- #define FM 0x02 /* mod: fetch pin mode */
- #define WRIE 0x01 /* mod: write and invalidate enable */
-
-/*1c*/ u_int32 nc_temp; /* ### Temporary stack */
-
-/*20*/ u_char nc_dfifo;
-/*21*/ u_char nc_ctest4;
- #define BDIS 0x80 /* mod: burst disable */
- #define MPEE 0x08 /* mod: master parity error enable */
-
-/*22*/ u_char nc_ctest5;
- #define DFS 0x20 /* mod: dma fifo size */
-/*23*/ u_char nc_ctest6;
-
-/*24*/ u_int32 nc_dbc; /* ### Byte count and command */
-/*28*/ u_int32 nc_dnad; /* ### Next command register */
-/*2c*/ u_int32 nc_dsp; /* --> Script Pointer */
-/*30*/ u_int32 nc_dsps; /* --> Script pointer save/opcode#2 */
-
-/*34*/ u_char nc_scratcha; /* Temporary register a */
-/*35*/ u_char nc_scratcha1;
-/*36*/ u_char nc_scratcha2;
-/*37*/ u_char nc_scratcha3;
-
-/*38*/ u_char nc_dmode;
- #define BL_2 0x80 /* mod: burst length shift value +2 */
- #define BL_1 0x40 /* mod: burst length shift value +1 */
- #define ERL 0x08 /* mod: enable read line */
- #define ERMP 0x04 /* mod: enable read multiple */
- #define BOF 0x02 /* mod: burst op code fetch */
-
-/*39*/ u_char nc_dien;
-/*3a*/ u_char nc_dwt;
-
-/*3b*/ u_char nc_dcntl; /* --> Script execution control */
-
- #define CLSE 0x80 /* mod: cache line size enable */
- #define PFF 0x40 /* cmd: pre-fetch flush */
- #define PFEN 0x20 /* mod: pre-fetch enable */
- #define SSM 0x10 /* mod: single step mode */
- #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
- #define STD 0x04 /* cmd: start dma mode */
- #define IRQD 0x02 /* mod: irq disable */
- #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
-
-/*3c*/ u_int32 nc_adder;
-
-/*40*/ u_short nc_sien; /* -->: interrupt enable */
-/*42*/ u_short nc_sist; /* <--: interrupt status */
- #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
- #define STO 0x0400/* sta: timeout (select) */
- #define GEN 0x0200/* sta: timeout (general) */
- #define HTH 0x0100/* sta: timeout (handshake) */
- #define MA 0x80 /* sta: phase mismatch */
- #define CMP 0x40 /* sta: arbitration complete */
- #define SEL 0x20 /* sta: selected by another device */
- #define RSL 0x10 /* sta: reselected by another device*/
- #define SGE 0x08 /* sta: gross error (over/underflow)*/
- #define UDC 0x04 /* sta: unexpected disconnect */
- #define RST 0x02 /* sta: scsi bus reset detected */
- #define PAR 0x01 /* sta: scsi parity error */
-
-/*44*/ u_char nc_slpar;
-/*45*/ u_char nc_swide;
-/*46*/ u_char nc_macntl;
-/*47*/ u_char nc_gpcntl;
-/*48*/ u_char nc_stime0; /* cmd: timeout for select&handshake*/
-/*49*/ u_char nc_stime1; /* cmd: timeout user defined */
-/*4a*/ u_short nc_respid; /* sta: Reselect-IDs */
-
-/*4c*/ u_char nc_stest0;
-
-/*4d*/ u_char nc_stest1;
- #define DBLEN 0x08 /* clock doubler running */
- #define DBLSEL 0x04 /* clock doubler selected */
-
-
-/*4e*/ u_char nc_stest2;
- #define ROF 0x40 /* reset scsi offset (after gross error!) */
- #define EXT 0x02 /* extended filtering */
-
-/*4f*/ u_char nc_stest3;
- #define TE 0x80 /* c: tolerAnt enable */
- #define HSC 0x20 /* c: Halt SCSI Clock */
- #define CSF 0x02 /* c: clear scsi fifo */
-
-/*50*/ u_short nc_sidl; /* Lowlevel: latched from scsi data */
-/*52*/ u_char nc_stest4;
- #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
- #define SMODE_HVD 0x40 /* High Voltage Differential */
- #define SMODE_SE 0x80 /* Single Ended */
- #define SMODE_LVD 0xc0 /* Low Voltage Differential */
- #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
-
-/*53*/ u_char nc_53_;
-/*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */
-/*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 */
-/*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */
-/*5a*/ u_short nc_5a_;
-/*5c*/ u_char nc_scr0; /* Working register B */
-/*5d*/ u_char nc_scr1; /* */
-/*5e*/ u_char nc_scr2; /* */
-/*5f*/ u_char nc_scr3; /* */
-/*60*/
-};
-
-/*-----------------------------------------------------------
-**
-** Utility macros for the script.
-**
-**-----------------------------------------------------------
-*/
-
-#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
-#define REG(r) REGJ (nc_, r)
-
-#ifndef TARGET_MODE


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

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

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part07

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


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.6 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

-#define TARGET_MODE 0
-#endif
-
-typedef u_int32 ncrcmd;
-
-/*-----------------------------------------------------------
-**
-** SCSI phases
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_DATA_OUT 0x00000000
-#define SCR_DATA_IN 0x01000000
-#define SCR_COMMAND 0x02000000
-#define SCR_STATUS 0x03000000
-#define SCR_ILG_OUT 0x04000000
-#define SCR_ILG_IN 0x05000000
-#define SCR_MSG_OUT 0x06000000
-#define SCR_MSG_IN 0x07000000
-
-/*-----------------------------------------------------------
-**
-** Data transfer via SCSI.
-**
-**-----------------------------------------------------------
-**
-** MOVE_ABS (LEN)
-** <<start address>>
-**
-** MOVE_IND (LEN)
-** <<dnad_offset>>
-**
-** MOVE_TBL
-** <<dnad_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_MOVE_ABS(l) ((0x08000000 ^ (TARGET_MODE << 1ul)) | (l))
-#define SCR_MOVE_IND(l) ((0x28000000 ^ (TARGET_MODE << 1ul)) | (l))
-#define SCR_MOVE_TBL (0x18000000 ^ (TARGET_MODE << 1ul))
-
-struct scr_tblmove {
- u_int32 size;
- u_int32 addr;
-};
-
-/*-----------------------------------------------------------
-**
-** Selection
-**
-**-----------------------------------------------------------
-**
-** SEL_ABS | SCR_ID (0..7) [ | REL_JMP]
-** <<alternate_address>>
-**
-** SEL_TBL | << dnad_offset>> [ | REL_JMP]
-** <<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SEL_ABS 0x40000000
-#define SCR_SEL_ABS_ATN 0x41000000
-#define SCR_SEL_TBL 0x42000000
-#define SCR_SEL_TBL_ATN 0x43000000
-
-struct scr_tblsel {
- u_char sel_0;
- u_char sel_sxfer;
- u_char sel_id;
- u_char sel_scntl3;
-};
-
-#define SCR_JMP_REL 0x04000000
-#define SCR_ID(id) (((u_int32)(id)) << 16)
-
-/*-----------------------------------------------------------
-**
-** Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-** WAIT_DISC
-** dummy: <<alternate_address>>
-**
-** WAIT_RESEL
-** <<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_WAIT_DISC 0x48000000
-#define SCR_WAIT_RESEL 0x50000000
-
-/*-----------------------------------------------------------
-**
-** Bit Set / Reset
-**
-**-----------------------------------------------------------
-**
-** SET (flags {|.. })
-**
-** CLR (flags {|.. })
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SET(f) (0x58000000 | (f))
-#define SCR_CLR(f) (0x60000000 | (f))
-
-#define SCR_CARRY 0x00000400
-#define SCR_TRG 0x00000200
-#define SCR_ACK 0x00000040
-#define SCR_ATN 0x00000008
-
-
-
-
-/*-----------------------------------------------------------
-**
-** Memory to memory move
-**
-**-----------------------------------------------------------
-**
-** COPY (bytecount)
-** << source_address >>
-** << destination_address >>
-**
-** SCR_COPY sets the NO FLUSH option by default.
-** SCR_COPY_F does not set this option.
-**
-** For chips which do not support this option,
-** ncr_copy_and_bind() will remove this bit.
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_FLUSH 0x01000000
-
-#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
-#define SCR_COPY_F(n) (0xc0000000 | (n))
-
-/*-----------------------------------------------------------
-**
-** Register move and binary operations
-**
-**-----------------------------------------------------------
-**
-** SFBR_REG (reg, op, data) reg = SFBR op data
-** << 0 >>
-**
-** REG_SFBR (reg, op, data) SFBR = reg op data
-** << 0 >>
-**
-** REG_REG (reg, op, data) reg = reg op data
-** << 0 >>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_REG_OFS(ofs) ((ofs) << 16ul)
-
-#define SCR_SFBR_REG(reg,op,data) \
- (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul))
-
-#define SCR_REG_SFBR(reg,op,data) \
- (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul))
-
-#define SCR_REG_REG(reg,op,data) \
- (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul))
-
-
-#define SCR_LOAD 0x00000000
-#define SCR_SHL 0x01000000
-#define SCR_OR 0x02000000
-#define SCR_XOR 0x03000000
-#define SCR_AND 0x04000000
-#define SCR_SHR 0x05000000
-#define SCR_ADD 0x06000000
-#define SCR_ADDC 0x07000000
-
-/*-----------------------------------------------------------
-**
-** FROM_REG (reg) SFBR = reg
-** << 0 >>
-**
-** TO_REG (reg) reg = SFBR
-** << 0 >>
-**
-** LOAD_REG (reg, data) reg = <data>
-** << 0 >>
-**
-** LOAD_SFBR(data) SFBR = <data>
-** << 0 >>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_FROM_REG(reg) \
- SCR_REG_SFBR(reg,SCR_OR,0)
-
-#define SCR_TO_REG(reg) \
- SCR_SFBR_REG(reg,SCR_OR,0)
-
-#define SCR_LOAD_REG(reg,data) \
- SCR_REG_REG(reg,SCR_LOAD,data)
-
-#define SCR_LOAD_SFBR(data) \
- (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
-
-/*-----------------------------------------------------------
-**
-** LOAD from memory to register.
-** STORE from register to memory.
-**
-**-----------------------------------------------------------
-**
-** LOAD_ABS (LEN)
-** <<start address>>
-**
-** LOAD_REL (LEN) (DSA relative)
-** <<dsa_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_FLUSH2 0x02000000
-#define SCR_DSA_REL2 0x10000000
-
-#define SCR_LOAD_R(reg, how, n) \
- (0xe1000000 | how | (SCR_REG_OFS(REG(reg))) | (n))
-
-#define SCR_STORE_R(reg, how, n) \
- (0xe0000000 | how | (SCR_REG_OFS(REG(reg))) | (n))
-
-#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
-#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
-#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
-
-#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
-#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
-#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
-
-
-/*-----------------------------------------------------------
-**
-** Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-** JUMP [ | IFTRUE/IFFALSE ( ... ) ]
-** <<address>>
-**
-** JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
-** <<distance>>
-**
-** CALL [ | IFTRUE/IFFALSE ( ... ) ]
-** <<address>>
-**
-** CALLR [ | IFTRUE/IFFALSE ( ... ) ]
-** <<distance>>
-**
-** RETURN [ | IFTRUE/IFFALSE ( ... ) ]
-** <<dummy>>
-**
-** INT [ | IFTRUE/IFFALSE ( ... ) ]
-** <<ident>>
-**
-** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
-** <<ident>>
-**
-** Conditions:
-** WHEN (phase)
-** IF (phase)
-** CARRY
-** DATA (data, mask)
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_OP 0x80000000
-#define SCR_JUMP 0x80080000
-#define SCR_JUMPR 0x80880000
-#define SCR_CALL 0x88080000
-#define SCR_CALLR 0x88880000
-#define SCR_RETURN 0x90080000
-#define SCR_INT 0x98080000
-#define SCR_INT_FLY 0x98180000
-
-#define IFFALSE(arg) (0x00080000 | (arg))
-#define IFTRUE(arg) (0x00000000 | (arg))
-
-#define WHEN(phase) (0x00030000 | (phase))
-#define IF(phase) (0x00020000 | (phase))
-
-#define DATA(D) (0x00040000 | ((D) & 0xff))
-#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
-
-#define CARRYSET (0x00200000)
-
-/*-----------------------------------------------------------
-**
-** SCSI constants.
-**
-**-----------------------------------------------------------
-*/
-
-/*
-** Messages
-*/
-
-#define M_COMPLETE (0x00)
-#define M_EXTENDED (0x01)
-#define M_SAVE_DP (0x02)
-#define M_RESTORE_DP (0x03)
-#define M_DISCONNECT (0x04)
-#define M_ID_ERROR (0x05)
-#define M_ABORT (0x06)
-#define M_REJECT (0x07)
-#define M_NOOP (0x08)
-#define M_PARITY (0x09)
-#define M_LCOMPLETE (0x0a)
-#define M_FCOMPLETE (0x0b)
-#define M_RESET (0x0c)
-#define M_ABORT_TAG (0x0d)
-#define M_CLEAR_QUEUE (0x0e)
-#define M_INIT_REC (0x0f)
-#define M_REL_REC (0x10)
-#define M_TERMINATE (0x11)
-#define M_SIMPLE_TAG (0x20)
-#define M_HEAD_TAG (0x21)
-#define M_ORDERED_TAG (0x22)
-#define M_IGN_RESIDUE (0x23)
-#define M_IDENTIFY (0x80)
-
-#define M_X_MODIFY_DP (0x00)
-#define M_X_SYNC_REQ (0x01)
-#define M_X_WIDE_REQ (0x03)
-
-/*
-** Status
-*/
-
-#define S_GOOD (0x00)
-#define S_CHECK_COND (0x02)
-#define S_COND_MET (0x04)
-#define S_BUSY (0x08)
-#define S_INT (0x10)
-#define S_INT_COND_MET (0x14)
-#define S_CONFLICT (0x18)
-#define S_TERMINATED (0x20)
-#define S_QUEUE_FULL (0x28)
-#define S_ILLEGAL (0xff)
-#define S_SENSE (0x80)
-
-/*
- * End of ncrreg from FreeBSD
- */
-
-#endif /* !defined HOSTS_C */
-
-#endif /* defined NCR53C8XX_H */
+#endif /* NCR53C8XX_H */
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c
--- v2.2.5/linux/drivers/scsi/pci2000.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/scsi/pci2000.c Tue Apr 13 07:54:02 1999
@@ -1,24 +1,22 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
X *
- * Copyright (c) 1999 Perceptive Solutions, Inc.
+ * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
X *
- * 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, or (at your option)
- * any later version.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
X *
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
X *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
X *
+ * Please send questions, comments, bug reports to:
+ * te...@psidisk.com Technical Support
X *
- * File Name: pci2000i.c
X *
X * Revisions 1.10 Jan-21-1999
X * - Fixed sign on message to reflect proper controller name.
@@ -28,16 +26,17 @@
X * - Fixed control timeout to not lock up the entire system if
X * controller goes offline completely.
X *
- *-M*************************************************************************/
-#define PCI2000_VERSION "1.11"
+ * Revisions 1.12 Mar-26-1999
+ * - Fixed spinlock and PCI configuration.
+ *
+ ****************************************************************************/
+#define PCI2000_VERSION "1.12"
X
X #include <linux/module.h>
X
X #include <linux/kernel.h>
-#include <linux/head.h>
X #include <linux/types.h>
X #include <linux/string.h>
-#include <linux/bios32.h>
X #include <linux/pci.h>
X #include <linux/ioport.h>
X #include <linux/delay.h>
@@ -49,11 +48,17 @@
X #include <linux/blk.h>
X #include "scsi.h"
X #include "hosts.h"
+#include <linux/stat.h>
X
X #include "pci2000.h"
X #include "psi_roy.h"
X
-#include<linux/stat.h>
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
+#include <linux/bios32.h>
+#endif
X
X struct proc_dir_entry Proc_Scsi_Pci2000 =
X { PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
@@ -91,6 +96,7 @@
X USHORT mb4;
X USHORT cmd;
X USHORT tag;
+ ULONG irqOwned;
X DEV2000 dev[MAX_BUS][MAX_UNITS];
X } ADAPTER2000, *PADAPTER2000;
X
@@ -234,6 +240,23 @@
X int pun;
X int bus;
X int z;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X
X DEB(printk ("\npci2000 recieved interrupt "));
X for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
@@ -252,7 +275,7 @@
X if ( !shost )
X {
X DEB (printk ("\npci2000: not my interrupt"));
- return;
+ goto irq_return;
X }
X
X padapter = HOSTDATA(shost);
@@ -276,7 +299,7 @@
X
X outb_p (0xFF, padapter->tag); // clear the op interrupt
X outb_p (CMD_DONE, padapter->cmd); // complete the op
- return; // done, but, with what?
+ goto irq_return;; // done, but, with what?
X
X irqProceed:;
X if ( tag & ERR08_TAGGED ) // is there an error here?
@@ -284,7 +307,7 @@
X if ( WaitReady (padapter) )
X {
X OpDone (SCpnt, DID_TIME_OUT << 16);
- return;
+ goto irq_return;;
X }
X
X outb_p (tag0, padapter->mb0); // get real error code
@@ -292,7 +315,7 @@
X if ( WaitReady (padapter) ) // wait for controller to suck up the op
X {
X OpDone (SCpnt, DID_TIME_OUT << 16);
- return;
+ goto irq_return;;
X }
X
X error = inl (padapter->mb0); // get error data
@@ -305,24 +328,40 @@
X if ( bus ) // are we doint SCSI commands?
X {
X OpDone (SCpnt, (DID_OK << 16) | 2);
- return;
+ goto irq_return;;
X }
X if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
X OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2); // test caller we have sense data too
X else
X OpDone (SCpnt, DID_ERROR << 16);
- return;
+ goto irq_return;;
X }
X OpDone (SCpnt, DID_ERROR << 16);
- return;
+ goto irq_return;;
X }
X
X outb_p (0xFF, padapter->tag); // clear the op interrupt
X outb_p (CMD_DONE, padapter->cmd); // complete the op
X OpDone (SCpnt, DID_OK << 16);
+
+irq_return:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X }
X /****************************************************************
- * Name: Pci2220i_QueueCommand
+ * Name: Pci2000_QueueCommand
X *
X * Description: Process a queued command from the SCSI manager.
X *
@@ -511,7 +550,7 @@
X if ( cmd )
X break;
X default:
- DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
+ DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
X OpDone (SCpnt, DID_ERROR << 16);
X return 0;
X }
@@ -538,7 +577,7 @@
X SCpnt->SCp.Status++;
X }
X /****************************************************************
- * Name: Pci2220i_Command
+ * Name: Pci2000_Command
X *
X * Description: Process a command from the SCSI manager.
X *
@@ -559,90 +598,121 @@
X return SCpnt->result;
X }
X /****************************************************************
- * Name: Pci2220i_Detect
+ * Name: Pci2000_Detect
X *
X * Description: Detect and initialize our boards.
X *
X * Parameters: tpnt - Pointer to SCSI host template structure.
X *
- * Returns: Number of adapters found.
+ * Returns: Number of adapters installed.
X *
X ****************************************************************/
X int Pci2000_Detect (Scsi_Host_Template *tpnt)
X {
- int pci_index = 0;
+ int found = 0;
+ int installed = 0;
X struct Scsi_Host *pshost;
X PADAPTER2000 padapter;
X int z, zz;
X int setirq;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ struct pci_dev *pdev = NULL;
+#else
+ UCHAR pci_bus, pci_device_fn;
+#endif
X
- if ( pcibios_present () )
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ if ( !pci_present () )
+#else
+ if ( !pcibios_present () )
+#endif
X {
- for ( pci_index = 0; pci_index <= MAXADAPTER; ++pci_index )
- {
- UCHAR pci_bus, pci_device_fn;
+ printk ("pci2000: PCI BIOS not present\n");
+ return 0;
+ }
X
- if ( pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
- break;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
+#else
+ while ( !pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, found, &pci_bus, &pci_device_fn) )
+#endif
+ {
+ pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
+ padapter = HOSTDATA(pshost);
X
- pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
- padapter = HOSTDATA(pshost);
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ padapter->basePort = pdev->base_address[1] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
+ padapter->basePort &= 0xFFFE;
+#endif
+ DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
+ padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
+ padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
+ padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
+ padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
+ padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
+ padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
+ padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
X
- pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
- padapter->basePort &= 0xFFFE;
- DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
- padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
- padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
- padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
- padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
- padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
- padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
- padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
-
- if ( WaitReady (padapter) )
- goto unregister;
- outb_p (0x84, padapter->mb0);
- outb_p (CMD_SPECIFY, padapter->cmd);
- if ( WaitReady (padapter) )
- goto unregister;
-
- pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
- setirq = 1;
- for ( z = 0; z < pci_index; z++ ) // scan for shared interrupts
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
+ if ( WaitReady (padapter) )
+ goto unregister;
+ outb_p (0x84, padapter->mb0);
+ outb_p (CMD_SPECIFY, padapter->cmd);
+ if ( WaitReady (padapter) )
+ goto unregister;
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ pshost->irq = pdev->irq;
+#else
+ pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+#endif
+ setirq = 1;
+ padapter->irqOwned = 0;
+ for ( z = 0; z < installed; z++ ) // scan for shared interrupts
+ {
+ if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
+ setirq = 0;
+ }
+ if ( setirq ) // if not shared, posses
+ {
+ if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
X {
- if ( request_irq (pshost->irq, Irq_Handler, 0, "pci2000", NULL) )
+ if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
X {
- printk ("Unable to allocate IRQ for PSI-2000 controller.\n");
+ printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
X goto unregister;
X }
X }
- PsiHost[pci_index] = pshost; // save SCSI_HOST pointer
+ padapter->irqOwned = pshost->irq; // set IRQ as owned
+ }
+ PsiHost[installed] = pshost; // save SCSI_HOST pointer
X
- pshost->unique_id = padapter->basePort;
- pshost->max_id = 16;
- pshost->max_channel = 1;
-
- for ( zz = 0; zz < MAX_BUS; zz++ )
- for ( z = 0; z < MAX_UNITS; z++ )
- padapter->dev[zz][z].tag = 0;
+ pshost->io_port = padapter->basePort;
+ pshost->n_io_port = 0xFF;
+ pshost->unique_id = padapter->basePort;
+ pshost->max_id = 16;
+ pshost->max_channel = 1;
+
+ for ( zz = 0; zz < MAX_BUS; zz++ )
+ for ( z = 0; z < MAX_UNITS; z++ )
+ padapter->dev[zz][z].tag = 0;
X
- printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %X IRQ = %d\n", padapter->basePort, pshost->irq);
- printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
+ printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %X IRQ = %d\n", padapter->basePort, pshost->irq);
+ printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
+ found++;
+ if ( ++installed < MAXADAPTER )
X continue;
+ break;
X unregister:;
- scsi_unregister (pshost);
- }
+ scsi_unregister (pshost);
+ found++;
X }
- NumAdapters = pci_index;
- return pci_index;
+ NumAdapters = installed;
+ return installed;
X }
X /****************************************************************
- * Name: Pci2220i_Abort
+ * Name: Pci2000_Abort
X *
X * Description: Process the Abort command from the SCSI manager.
X *
@@ -657,7 +727,7 @@
X return SCSI_ABORT_SNOOZE;
X }
X /****************************************************************
- * Name: Pci2220i_Reset
+ * Name: Pci2000_Reset
X *
X * Description: Process the Reset command from the SCSI manager.
X *
@@ -675,11 +745,34 @@
X {
X return SCSI_RESET_PUNT;
X }
+/****************************************************************
+ * Name: Pci2000_Release
+ *
+ * Description: Release resources allocated for a single each adapter.
+ *
+ * Parameters: pshost - Pointer to SCSI command structure.
+ *
+ * Returns: zero.
+ *
+ ****************************************************************/
+int Pci2000_Release (struct Scsi_Host *pshost)
+ {
+ PADAPTER2000 padapter = HOSTDATA (pshost);
X
-#include "sd.h"
+ if ( padapter->irqOwned )
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+ free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+ free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+ release_region (pshost->io_port, pshost->n_io_port);
+ scsi_unregister(pshost);
+ return 0;
+ }
X
+#include "sd.h"
X /****************************************************************
- * Name: Pci2220i_BiosParam
+ * Name: Pci2000_BiosParam
X *
X * Description: Process the biosparam request from the SCSI manager to
X * return C/H/S data.
@@ -713,7 +806,7 @@
X
X #ifdef MODULE
X /* Eventually this will go into an include file, but this will be later */
-Scsi_Host_Template driver_template = PCI2220I;
+Scsi_Host_Template driver_template = PCI2000;
X
X #include "scsi_module.c"
X #endif
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/pci2000.h linux/drivers/scsi/pci2000.h
--- v2.2.5/linux/drivers/scsi/pci2000.h Tue Mar 23 14:35:48 1999
+++ linux/drivers/scsi/pci2000.h Fri Apr 16 14:28:51 1999
@@ -1,29 +1,23 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
X *
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * pci2000.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
X *
- * 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, or (at your option)
- * any later version.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
X *
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
X *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
X *
+ * Please send questions, comments, bug reports to:
+ * te...@psidisk.com Technical Support
X *
- * File Name: pci2000.h
- *
- * Description: Header file for the SCSI driver for the PCI-2000
- * interface card.
- *
- *-M*************************************************************************/
+ ****************************************************************************/
X #ifndef _PCI2000_H
X #define _PCI2000_H
X
@@ -33,6 +27,11 @@
X #ifndef PSI_EIDE_SCSIOP
X #define PSI_EIDE_SCSIOP 1
X
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+#define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s))
+
X /************************************************/
X /* definition of standard data types */
X /************************************************/
@@ -194,6 +193,7 @@
X int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
X int Pci2000_Abort (Scsi_Cmnd *SCpnt);
X int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int flags);
+int Pci2000_Release (struct Scsi_Host *pshost);
X int Pci2000_BiosParam (Disk *disk, kdev_t dev, int geom[]);
X
X #ifndef NULL
@@ -202,12 +202,43 @@
X
X extern struct proc_dir_entry Proc_Scsi_Pci2000;
X
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
+#define PCI2000 { \
+ next: NULL, \
+ module: NULL, \
+ proc_dir: &Proc_Scsi_Pci2000, \
+ proc_info: NULL, /* let's not bloat the kernel */ \
+ name: "PCI-2000 SCSI Intelligent Disk Controller",\
+ detect: Pci2000_Detect, \
+ release: Pci2000_Release, \
+ info: NULL, /* let's not bloat the kernel */ \
+ command: Pci2000_Command, \
+ queuecommand: Pci2000_QueueCommand, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: Pci2000_Abort, \
+ reset: Pci2000_Reset, \
+ slave_attach: NULL, \
+ bios_param: Pci2000_BiosParam, \
+ can_queue: 16, \
+ this_id: -1, \
+ sg_tablesize: 16, \
+ cmd_per_lun: 1, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: DISABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+ }
+#else
X #define PCI2000 { NULL, NULL, \
X &Proc_Scsi_Pci2000,/* proc_dir_entry */ \
X NULL, \
X "PCI-2000 SCSI Intelligent Disk Controller",\
X Pci2000_Detect, \
- NULL, \
+ Pci2000_Release, \
X NULL, \
X Pci2000_Command, \
X Pci2000_QueueCommand, \
@@ -222,5 +253,6 @@
X 0, \
X 0, \
X DISABLE_CLUSTERING }
+#endif
X
X #endif
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- v2.2.5/linux/drivers/scsi/pci2220i.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/scsi/pci2220i.c Tue Apr 13 07:54:02 1999
@@ -1,35 +1,36 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-22220I device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
X *
- * Copyright (c) 1999 Perceptive Solutions, Inc.
+ * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
X *
- * 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, or (at your option)
- * any later version.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
X *
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
X *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
X *
+ * Please send questions, comments, bug reports to:
+ * te...@psidisk.com Technical Support
X *
- * File Name: pci2220i.c
X *
- * Description: SCSI driver for the PCI2220I EIDE interface card.
+ * Revisions 1.10 Mar-26-1999
+ * - Updated driver for RAID and hot reconstruct support.
X *
- *-M*************************************************************************/
+ * Revisions 1.11 Mar-26-1999
+ * - Fixed spinlock and PCI configuration.
+ *
+ ****************************************************************************/
X
X #include <linux/module.h>
X #include <linux/kernel.h>
-#include <linux/head.h>
X #include <linux/types.h>
X #include <linux/string.h>
-#include <linux/bios32.h>
+#include <linux/malloc.h>
X #include <linux/pci.h>
X #include <linux/ioport.h>
X #include <linux/delay.h>
@@ -46,7 +47,14 @@
X #include "hosts.h"
X #include "pci2220i.h"
X
-#define PCI2220I_VERSION "1.10"
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
+#include <linux/bios32.h>
+#endif
+
+#define PCI2220I_VERSION "1.11"
X //#define READ_CMD IDE_COMMAND_READ
X //#define WRITE_CMD IDE_COMMAND_WRITE
X //#define MAX_BUS_MASTER_BLOCKS 1 // This is the maximum we can bus master
@@ -119,6 +127,7 @@
X USHORT timingMode; // timing mode currently set for adapter
X USHORT timingPIO; // TRUE if PIO timing is active
X ULONG timingAddress; // address to use on adapter for current timing mode
+ ULONG irqOwned; // owned IRQ or zero if shared
X OUR_DEVICE device[DALE_MAXDRIVES];
X DISK_MIRROR *raidData[8];
X ULONG startSector;
@@ -135,9 +144,9 @@
X USHORT demoFail; // flag for RAID failure demonstration
X USHORT survivor;
X USHORT failinprog;
- USHORT timeoutReconRetry;
X struct timer_list reconTimer;
X struct timer_list timer;
+ UCHAR *kBuffer;
X } ADAPTER2220I, *PADAPTER2220I;
X
X #define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
@@ -155,7 +164,6 @@
X static SETUP DaleSetup;
X static DISK_MIRROR DiskMirror[2];
X static ULONG ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
-static UCHAR Buffer[SECTORSXFER * BYTES_PER_SECTOR];
X
X static void ReconTimerExpiry (unsigned long data);
X
@@ -523,7 +531,7 @@
X ****************************************************************/
X static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
X {
- PIDENTIFY_DATA pid = (PIDENTIFY_DATA)Buffer;
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
X
X SelectSpigot (padapter, spigot | 0x80); // select the spigot
X outb_p (device << 4, padapter->regLba24); // select the drive
@@ -532,10 +540,51 @@
X WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
X if ( WaitDrq (padapter) )
X return 0;
- insw (padapter->regData, Buffer, sizeof (IDENTIFY_DATA) >> 1);
+ insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
X return (pid->LBATotalSectors - 1);
X }
X /****************************************************************
+ * Name: InlineReadSignature :LOCAL
+ *
+ * Description: Do an inline read RAID sigature.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
+ * index - index of data to read.
+ *
+ * Returns: Zero if no error or status register contents on error.
+ *
+ ****************************************************************/
+static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
+ {
+ UCHAR status;
+ UCHAR spigot = 1 << index;
+ ULONG zl = pdev->lastsectorlba[index];
+
+ SelectSpigot (padapter, spigot | 0x80); // select the spigot without interrupts
+ outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
+ status = WaitReady (padapter);
+ if ( !status )
+ {
+ outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
+ outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
+ outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
+ outb_p (1, padapter->regSectCount);
+ WriteCommand (padapter, IDE_COMMAND_READ);
+ status = WaitDrq (padapter);
+ if ( !status )
+ {
+ insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
+ ((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
+ ((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
+ // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
+ WaitReady (padapter);


+ return 0;
+ }
+ }

+ return status;
+ }
+/****************************************************************
X * Name: DecodeError :LOCAL
X *
X * Description: Decode and process device errors.
@@ -619,9 +668,9 @@
X StartTimer (padapter);
X padapter->expectingIRQ = TRUE;
X
- outsw (padapter->regData, Buffer, DISK_MIRROR_POSITION / 2);
- outsw (padapter->regData, &pdev->DiskMirror[index], sizeof (DISK_MIRROR) / 2);
- outsw (padapter->regData, Buffer, ((512 - (DISK_MIRROR_POSITION + sizeof (DISK_MIRROR))) / 2));
+ ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
+ ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
+ outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
X return FALSE;
X }
X /*******************************************************************************************************
@@ -640,7 +689,7 @@
X {
X UCHAR spigot;
X
- DEB (printk ("\npci2000i: Initialize failover process - survivor = %d", padapter->survivor));
+ DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", padapter->survivor));
X pdev->raid = FALSE; //initializes system for non raid mode
X pdev->hotRecon = 0;
X padapter->reconOn = FALSE;
@@ -674,71 +723,75 @@
X {
X PADAPTER2220I padapter = (PADAPTER2220I)data;
X POUR_DEVICE pdev = padapter->pdev;
- ULONG flags;
X UCHAR status = IDE_STATUS_BUSY;
X UCHAR temp, temp1;
-
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X DEB (printk ("\nPCI2220I: Timeout expired "));
- save_flags (flags);
- cli ();
X
X if ( padapter->failinprog )
X {
X DEB (printk ("in failover process"));
- restore_flags (flags);
X OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
- return;
+ goto timerExpiryDone;
X }
X
X while ( padapter->reconPhase )
X {
X DEB (printk ("in recon phase %X", padapter->reconPhase));
- if ( --padapter->timeoutReconRetry )
- {
- StartTimer (padapter);
- return;
- }
X switch ( padapter->reconPhase )
X {
X case RECON_PHASE_MARKING:
X case RECON_PHASE_LAST:
X padapter->survivor = (pdev->spigot ^ 3) >> 1;
- restore_flags (flags);
X DEB (printk ("\npci2220i: FAILURE 1"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
X
X case RECON_PHASE_READY:
X OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
X
X case RECON_PHASE_COPY:
X padapter->survivor = (pdev->spigot) >> 1;
- restore_flags (flags);
X DEB (printk ("\npci2220i: FAILURE 2"));
+ DEB (printk ("\n spig/stat = %X", inb_p (padapter->regStatSel));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
X
X case RECON_PHASE_UPDATE:
X padapter->survivor = (pdev->spigot) >> 1;
- restore_flags (flags);
- DEB (printk ("\npci2220i: FAILURE 3"));
+ DEB (printk ("\npci2220i: FAILURE 3")));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
X
X case RECON_PHASE_END:
X padapter->survivor = (pdev->spigot) >> 1;
- restore_flags (flags);
X DEB (printk ("\npci2220i: FAILURE 4"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
X
X default:
- return;
+ goto timerExpiryDone;
X }
X }
X
@@ -779,14 +832,13 @@
X padapter->survivor = 1;
X else
X padapter->survivor = 0;
- restore_flags (flags);
- DEB (printk ("\npci2220i: FAILURE 5"));
+ DEB (printk ("\npci2220i: FAILURE 5"));
X if ( InitFailover (padapter, pdev) )
X {
X status = inb_p (padapter->regStatCmd);
X break;
X }
- return;
+ goto timerExpiryDone;
X }
X }
X }
@@ -794,14 +846,13 @@
X {
X DEB (printk ("in RAID read operation"));
X padapter->survivor = (pdev->spigot ^ 3) >> 1;
- restore_flags (flags);
X DEB (printk ("\npci2220i: FAILURE 6"));
X if ( InitFailover (padapter, pdev) )
X {
X status = inb_p (padapter->regStatCmd);
X break;
X }
- return;
+ goto timerExpiryDone;
X }
X }
X else
@@ -812,8 +863,23 @@
X break;
X }
X
- restore_flags (flags);
X OpDone (padapter, DecodeError (padapter, status));
+
+timerExpiryDone:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X }
X /****************************************************************
X * Name: SetReconstruct :LOCAL
@@ -854,15 +920,31 @@
X USHORT minmode;
X ULONG zl;
X UCHAR zc;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X
X padapter = (PADAPTER2220I)data;
X if ( padapter->SCpnt )
- return;
+ goto reconTimerExpiry;
X
X pdev = padapter->device;
- pid = (PIDENTIFY_DATA)Buffer;
+ pid = (PIDENTIFY_DATA)padapter->kBuffer;
X padapter->reconTimer.data = 0;
- padapter->timeoutReconRetry = 2;
X padapter->pdev = pdev;
X if ( padapter->reconIsStarting )
X {
@@ -875,7 +957,7 @@
X {
X if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
X {
- return;
+ goto reconTimerExpiry;
X }
X
X if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
@@ -900,7 +982,7 @@
X }
X
X if ( !pdev->hotRecon )
- return;
+ goto reconTimerExpiry;
X
X zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
X outb_p (zc | pdev->hotRecon | 0x40, padapter->regFail);
@@ -976,15 +1058,15 @@
X padapter->reconPhase = RECON_PHASE_FAILOVER;
X DEB (printk ("\npci2220i: FAILURE 7"));
X InitFailover (padapter, pdev);
- return;
+ goto reconTimerExpiry;
X }
X
X pdev->raid = TRUE;
X
X if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
- return;
+ goto reconTimerExpiry;
X padapter->reconPhase = RECON_PHASE_MARKING;
- return;
+ goto reconTimerExpiry;
X }
X
X //**********************************
@@ -999,10 +1081,10 @@
X padapter->reconPhase = RECON_PHASE_FAILOVER;
X DEB (printk ("\npci2220i: FAILURE 8"));
X InitFailover (padapter, pdev);
- return;
+ goto reconTimerExpiry;
X }
X padapter->reconPhase = RECON_PHASE_UPDATE;
- return;
+ goto reconTimerExpiry;
X }
X
X zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
@@ -1016,7 +1098,7 @@
X outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);// select the drive
X SelectSpigot (padapter, pdev->spigot);
X if ( WaitReady (padapter) )
- return;
+ goto reconTimerExpiry;
X
X SelectSpigot (padapter, pdev->hotRecon);
X if ( WaitReady (padapter) )
@@ -1025,7 +1107,7 @@
X padapter->reconPhase = RECON_PHASE_FAILOVER;
X DEB (printk ("\npci2220i: FAILURE 9"));
X InitFailover (padapter, pdev);
- return;
+ goto reconTimerExpiry;
X }
X
X SelectSpigot (padapter, 3);
@@ -1040,15 +1122,30 @@
X StartTimer (padapter);
X SelectSpigot (padapter, pdev->spigot);
X WriteCommand (padapter, READ_CMD);
- return;
+ goto reconTimerExpiry;
X }
X
X pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
X pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
X if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
- return;
+ goto reconTimerExpiry;
X padapter->reconPhase = RECON_PHASE_LAST;
- return;
+
+reconTimerExpiry:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X }
X /****************************************************************
X * Name: Irq_Handler :LOCAL
@@ -1072,6 +1169,23 @@
X UCHAR status1;
X int z;
X ULONG zl;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X
X // DEB (printk ("\npci2220i recieved interrupt\n"));
X
@@ -1090,7 +1204,7 @@
X if ( !shost )
X {
X DEB (printk ("\npci2220i: not my interrupt"));
- return;
+ goto irq_return;
X }
X
X padapter = HOSTDATA(shost);
@@ -1101,7 +1215,7 @@
X {
X DEB(printk ("\npci2220i Unsolicited interrupt\n"));
X STOP_HERE ();
- return;
+ goto irq_return;
X }
X padapter->expectingIRQ = 0;
X outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
@@ -1125,7 +1239,7 @@
X OpDone (padapter, DID_OK << 16);
X else
X Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
- return;
+ goto irq_return;
X }
X }
X
@@ -1142,24 +1256,24 @@
X if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
X {
X padapter->survivor = (pdev->spigot ^ 3) >> 1;
- DEB (printk ("\npci2220i: FAILURE 10"));
+ DEB (printk ("\npci2220i: FAILURE 10"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
X }
X if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
X {
X padapter->survivor = (pdev->spigot) >> 1;
- DEB (printk ("\npci2220i: FAILURE 11"));
+ DEB (printk ("\npci2220i: FAILURE 11"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
X }
X padapter->reconPhase = RECON_PHASE_END;
- return;
+ goto irq_return;
X }
X OpDone (padapter, DID_OK << 16);
- return;
+ goto irq_return;
X
X case RECON_PHASE_READY:
X status = inb_p (padapter->regStatCmd); // read the device status
@@ -1167,7 +1281,7 @@
X {
X del_timer (&padapter->timer);
X OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
X }
X SelectSpigot (padapter, pdev->hotRecon);
X if ( WaitDrq (padapter) )
@@ -1177,25 +1291,25 @@
X DEB (printk ("\npci2220i: FAILURE 12"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
X }
X SelectSpigot (padapter, pdev->spigot | 0x40);
X padapter->reconPhase = RECON_PHASE_COPY;
X padapter->expectingIRQ = TRUE;
X if ( padapter->timingPIO )
X {
- insw (padapter->regData, Buffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
+ insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
X }
X else
X {
X outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (virt_to_bus (Buffer), padapter->regDmaAddrPci);
+ outl (virt_to_bus (padapter->kBuffer), padapter->regDmaAddrPci);
X outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
X outb_p (8, padapter->regDmaDesc); // read operation
X outb_p (1, padapter->regDmaMode); // no interrupt
X outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
X }
- return;
+ goto irq_return;
X
X case RECON_PHASE_COPY:
X pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
@@ -1207,14 +1321,13 @@
X if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
X {
X padapter->survivor = (pdev->spigot) >> 1;
- DEB (printk ("\npci2220i: FAILURE 13"));
- DEB (printk (" status = %X error = %X", status, inb_p (padapter->regError)));
+ DEB (printk ("\npci2220i: FAILURE 13"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
X }
X OpDone (padapter, DID_OK << 16);
- return;
+ goto irq_return;
X
X case RECON_PHASE_END:
X status = inb_p (padapter->regStatCmd); // read the device status
@@ -1225,15 +1338,15 @@
X DEB (printk ("\npci2220i: FAILURE 14"));
X if ( InitFailover (padapter, pdev) )
X OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
X }
X padapter->reconOn = FALSE;
X pdev->hotRecon = 0;
X OpDone (padapter, DID_OK << 16);
- return;
+ goto irq_return;
X
X default:
- return;
+ goto irq_return;
X }
X }
X
@@ -1251,7 +1364,7 @@
X del_timer (&padapter->timer);
X DEB (printk ("\npci2220i: FAILURE 15"));
X if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
X }
X break;
X }
@@ -1270,7 +1383,7 @@
X else
X BusMaster (padapter, 1, 1);
X padapter->expectingIRQ = TRUE;
- return;
+ goto irq_return;
X }
X status = 0;
X break;
@@ -1295,7 +1408,7 @@
X SelectSpigot (padapter, pdev->spigot | 0x80);
X DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
X if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
X }
X break;
X }
@@ -1307,7 +1420,7 @@
X del_timer (&padapter->timer);
X DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
X if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
X status = status1;
X break;
X }
@@ -1320,13 +1433,13 @@
X del_timer (&padapter->timer);
X DEB (printk ("\npci2220i: FAILURE 18"));
X if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
X SelectSpigot (padapter, status | 0x80);
X status = inb_p (padapter->regStatCmd); // read the device status
X break;
X }
X padapter->expectingIRQ = TRUE;
- return;
+ goto irq_return;
X }
X status = 0;
X break;
@@ -1338,7 +1451,7 @@
X if ( status )
X break;
X padapter->expectingIRQ = TRUE;
- return;
+ goto irq_return;
X }
X status = 0;
X break;
@@ -1346,7 +1459,7 @@
X case IDE_COMMAND_IDENTIFY:
X {
X PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
- PIDENTIFY_DATA pid = (PIDENTIFY_DATA)Buffer;
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
X
X status = inb_p (padapter->regStatCmd);
X if ( status & IDE_STATUS_DRQ )
@@ -1399,6 +1512,21 @@
X zl = DID_OK << 16;
X
X OpDone (padapter, zl);
+irq_return:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
X }
X /****************************************************************
X * Name: Pci2220i_QueueCommand
@@ -1652,12 +1780,13 @@
X *
X * Parameters: tpnt - Pointer to SCSI host template structure.
X *
- * Returns: Number of adapters found.
+ * Returns: Number of adapters installed.
X *
X ****************************************************************/
X int Pci2220i_Detect (Scsi_Host_Template *tpnt)
X {
- int pci_index = 0;
+ int found = 0;
+ int installed = 0;
X struct Scsi_Host *pshost;
X PADAPTER2220I padapter;
X int unit;
@@ -1667,174 +1796,223 @@
X int setirq;
X UCHAR spigot1 = FALSE;
X UCHAR spigot2 = FALSE;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ struct pci_dev *pdev = NULL;
+#else
+ UCHAR pci_bus, pci_device_fn;
+#endif
X
- if ( pcibios_present () )
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ if ( !pci_present () )
+#else
+ if ( !pcibios_present () )
+#endif
X {
- for ( pci_index = 0; pci_index <= MAXADAPTER; ++pci_index )
- {
- UCHAR pci_bus, pci_device_fn;
+ printk ("pci2220i: PCI BIOS not present\n");
+ return 0;
+ }
X
- if ( pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
- break;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL )
+#else
+ while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) )
+#endif
+ {
+ pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
+ padapter = HOSTDATA(pshost);
+ memset (padapter, 0, sizeof (ADAPTER2220I));
X
- pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
- padapter = HOSTDATA(pshost);
- memset (padapter, 0, sizeof (ADAPTER2220I));
-
- pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs);
- zs &= 0xFFFE;
- padapter->basePort = zs;
- padapter->regRemap = zs + RTR_LOCAL_REMAP; // 32 bit local space remap
- padapter->regDesc = zs + RTR_REGIONS; // 32 bit local region descriptor
- padapter->regRange = zs + RTR_LOCAL_RANGE; // 32 bit local range
- padapter->regIrqControl = zs + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
- padapter->regScratchPad = zs + RTR_MAILBOX; // 16 byte scratchpad I/O base address
-
- pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs);
- zs &= 0xFFFE;
- padapter->regBase = zs;
- padapter->regData = zs + REG_DATA; // data register I/O address
- padapter->regError = zs + REG_ERROR; // error register I/O address
- padapter->regSectCount = zs + REG_SECTOR_COUNT; // sector count register I/O address
- padapter->regLba0 = zs + REG_LBA_0; // least significant byte of LBA
- padapter->regLba8 = zs + REG_LBA_8; // next least significant byte of LBA
- padapter->regLba16 = zs + REG_LBA_16; // next most significan byte of LBA
- padapter->regLba24 = zs + REG_LBA_24; // head and most 4 significant bits of LBA
- padapter->regStatCmd = zs + REG_STAT_CMD; // status on read and command on write register
- padapter->regStatSel = zs + REG_STAT_SEL; // board status on read and spigot select on write register
- padapter->regFail = zs + REG_FAIL;
- padapter->regAltStat = zs + REG_ALT_STAT;
-
- padapter->regDmaDesc = zs + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
- padapter->regDmaCmdStat = zs + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
- padapter->regDmaAddrPci = zs + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
- padapter->regDmaAddrLoc = zs + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
- padapter->regDmaCount = zs + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
- padapter->regDmaMode = zs + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
-
- if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
- goto unregister;
-
- pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
- setirq = 1;
- for ( z = 0; z < pci_index; z++ ) // scan for shared interrupts
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ zs = pdev->base_address[1] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs);
+ zs &= 0xFFFE;
+#endif
+ padapter->basePort = zs;
+ padapter->regRemap = zs + RTR_LOCAL_REMAP; // 32 bit local space remap
+ padapter->regDesc = zs + RTR_REGIONS; // 32 bit local region descriptor
+ padapter->regRange = zs + RTR_LOCAL_RANGE; // 32 bit local range
+ padapter->regIrqControl = zs + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
+ padapter->regScratchPad = zs + RTR_MAILBOX; // 16 byte scratchpad I/O base address
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ zs = pdev->base_address[2] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs);
+ zs &= 0xFFFE;
+#endif
+ padapter->regBase = zs;
+ padapter->regData = zs + REG_DATA; // data register I/O address
+ padapter->regError = zs + REG_ERROR; // error register I/O address
+ padapter->regSectCount = zs + REG_SECTOR_COUNT; // sector count register I/O address
+ padapter->regLba0 = zs + REG_LBA_0; // least significant byte of LBA
+ padapter->regLba8 = zs + REG_LBA_8; // next least significant byte of LBA
+ padapter->regLba16 = zs + REG_LBA_16; // next most significan byte of LBA
+ padapter->regLba24 = zs + REG_LBA_24; // head and most 4 significant bits of LBA
+ padapter->regStatCmd = zs + REG_STAT_CMD; // status on read and command on write register


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 07'
echo 'File patch-2.2.6 is continued in part 08'
echo 08 > _shar_seq_.tmp

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part16

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


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.6 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

+ if(! scsi_block_when_processing_errors(sdp->device) )
+ return -ENXIO;
+
+ switch(cmd_in)
X {
- copy_to_user(buf,&device->header,sizeof(struct sg_header));
- buf+=sizeof(struct sg_header);
- if (count>device->header.pack_len)
- count=device->header.pack_len;
- if (count > sizeof(struct sg_header)) {
- copy_to_user(buf,device->buff,count-sizeof(struct sg_header));
- }
+ case SG_SET_TIMEOUT:
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ return get_user(sfp->timeout, (int *)arg);
+ case SG_GET_TIMEOUT:
+ return sfp->timeout; /* strange ..., for backward compatibility */
+ case SG_SET_FORCE_LOW_DMA:
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ if (val) {
+ if ((0 == sfp->low_dma) && (0 == sg_fb_in_use(sfp))) {
+ sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
+ sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, 1,
+ SG_HEAP_PAGE, &sfp->fb_size);
+ }
+ sfp->low_dma = 1;
+ if (! sfp->fst_buf)
+ return -ENOMEM;
+ }
+ else
+ sfp->low_dma = sdp->device->host->unchecked_isa_dma;
+ return 0;
+ case SG_GET_LOW_DMA:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ put_user((int)sfp->low_dma, (int *)arg);
+ return 0;
+ case SG_GET_SCSI_ID:
+ result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(Sg_scsi_id));
+ if (result) return result;
+ else {
+ Sg_scsi_id * sg_idp = (Sg_scsi_id *)arg;
+ put_user((int)sdp->device->host->host_no, &sg_idp->host_no);
+ put_user((int)sdp->device->channel, &sg_idp->channel);
+ put_user((int)sdp->device->id, &sg_idp->scsi_id);
+ put_user((int)sdp->device->lun, &sg_idp->lun);
+ put_user((int)sdp->device->type, &sg_idp->scsi_type);
+ put_user(0, &sg_idp->unused1);
+ put_user(0, &sg_idp->unused2);
+ put_user(0, &sg_idp->unused3);
+ return 0;
+ }
+ case SG_SET_FORCE_PACK_ID:
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sfp->force_packid = val ? 1 : 0;
+ return 0;
+ case SG_GET_PACK_ID:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ srp = sfp->headrp;
+ while (srp) {
+ if (! srp->my_cmdp) {
+ put_user(srp->header.pack_id, (int *)arg);
+ return 0;
+ }
+ srp = srp->nextrp;
+ }
+ put_user(-1, (int *)arg);
+ return 0;
+ case SG_GET_NUM_WAITING:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ srp = sfp->headrp;
+ val = 0;
+ while (srp) {
+ if (! srp->my_cmdp)
+ ++val;
+ srp = srp->nextrp;
+ }
+ put_user(val, (int *)arg);
+ return 0;
+ case SG_GET_SG_TABLESIZE:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ put_user(sdp->sg_tablesize, (int *)arg);
+ return 0;
+ case SG_SET_RESERVED_SIZE:
+ /* currently ignored, future extension */
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES;
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ return 0;
+ case SG_GET_RESERVED_SIZE:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ put_user(sfp->fb_size, (int *)arg);
+ return 0;
+ case SG_GET_MERGE_FD:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ put_user((int)sdp->merge_fd, (int *)arg);
+ return 0;
+ case SG_SET_MERGE_FD:
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES; /* require write access since effect wider
+ then just this fd */
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ val = val ? 1 : 0;
+ if ((val ^ (0 != sdp->merge_fd)) &&
+ sdp->headfp && sdp->headfp->nextfp)
+ return -EBUSY; /* too much work if multiple fds already */
+ sdp->merge_fd = val;
+ return 0;
+ case SG_SET_COMMAND_Q:
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sfp->cmd_q = val ? 1 : 0;
+ return 0;
+ case SG_GET_COMMAND_Q:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ put_user((int)sfp->cmd_q, (int *)arg);
+ return 0;
+ case SG_EMULATED_HOST:
+ return put_user(sdp->device->host->hostt->emulated, (int *)arg);
+ case SCSI_IOCTL_SEND_COMMAND:
+ /* Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
+ user already has read/write access to the generic device and so
+ can execute arbitrary SCSI commands. */
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES; /* require write access since these could be
+ dangerous */
+ return scsi_ioctl_send_command(sdp->device, (void *)arg);
+ case SG_SET_DEBUG:
+ result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ if (result) return result;
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sdp->sgdebug = (char)val;
+ if (9 == sdp->sgdebug)
+ sg_debug(sdp, sfp, 0);
+ else if (sdp->sgdebug > 9)
+ sg_debug_all(sfp);
+ return 0;
+ case SCSI_IOCTL_GET_IDLUN:
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
+ default:
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES; /* require write access since these could be
+ dangerous */
+ return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
X }
- else
- count= device->header.result==0 ? 0 : -EIO;
+}
X
- /*
- * Clean up, and release the device so that we can send another
- * command.
- */
- sg_free(device->buff,device->buff_len);
- device->buff = NULL;
- device->pending=0;
- wake_up(&device->write_wait);
- return count;
+static unsigned int sg_poll(struct file * filp, poll_table * wait)
+{
+ unsigned int res = 0;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp;
+ int count = 0;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return POLLERR;
+ poll_wait(filp, &sfp->read_wait, wait);
+ srp = sfp->headrp;
+ while (srp) { /* if any read waiting, flag it */
+ if (! (res || srp->my_cmdp))
+ res = POLLIN | POLLRDNORM;
+ ++count;
+ srp = srp->nextrp;
+ }
+ if (0 == sfp->cmd_q) {
+ if (0 == count)
+ res |= POLLOUT | POLLWRNORM;
+ }
+ else if (count < SG_MAX_QUEUE)
+ res |= POLLOUT | POLLWRNORM;
+ SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",
+ MINOR(sdp->i_rdev), (int)res));
+ return res;
X }
X
-/*
- * This function is called by the interrupt handler when we
+static int sg_fasync(int fd, struct file * filp, int mode)
+{
+ int retval;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",
+ MINOR(sdp->i_rdev), mode));
+
+ retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
+ return (retval < 0) ? retval : 0;
+}
+
+/* This function is called by the interrupt handler when we
X * actually have a command that is complete. Change the
- * flags to indicate that we have a result.
- */
+ * flags to indicate that we have a result. */
X static void sg_command_done(Scsi_Cmnd * SCpnt)
X {
X int dev = MINOR(SCpnt->request.rq_dev);
- struct scsi_generic *device = &scsi_generics[dev];
- if (!device->pending)
- {
- printk("unexpected done for sg %d\n",dev);
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp = NULL;
+ int closed = 0;
+
+ if ((NULL == sg_dev_arr) || (dev < 0) || (dev >= sg_template.dev_max)) {
+ SCSI_LOG_TIMEOUT(1, printk("sg__done: bad args dev=%d\n", dev));
X scsi_release_command(SCpnt);
X SCpnt = NULL;
- return;
+ return;
X }
-
- /*
- * See if the command completed normally, or whether something went
- * wrong.
- */
- memcpy(device->header.sense_buffer, SCpnt->sense_buffer,
- sizeof(SCpnt->sense_buffer));
- switch (host_byte(SCpnt->result)) {
+ sdp = &sg_dev_arr[dev];
+ if (NULL == sdp->device)
+ return; /* Get out of here quick ... */
+ sfp = sdp->headfp;
+ while (sfp) {
+ srp = sfp->headrp;
+ while (srp) {
+ if (SCpnt == srp->my_cmdp)
+ break;
+ srp = srp->nextrp;
+ }
+ if (srp)
+ break;
+ sfp = sfp->nextfp;
+ }
+ if (! srp) {
+ SCSI_LOG_TIMEOUT(1, printk("sg__done: req missing, dev=%d\n", dev));
+ scsi_release_command(SCpnt);
+ SCpnt = NULL;
+ return;
+ }
+/* First transfer ownership of data buffers to sg_device object. */
+ srp->data.use_sg = SCpnt->use_sg;
+ srp->data.sglist_len = SCpnt->sglist_len;
+ srp->data.bufflen = SCpnt->bufflen;
+ srp->data.buffer = SCpnt->buffer;
+ sg_clr_scpnt(SCpnt);
+ srp->my_cmdp = NULL;
+
+ SCSI_LOG_TIMEOUT(4,
+ printk("sg__done: dev=%d, scsi_stat=%d, res=0x%x\n",
+ dev, (int)status_byte(SCpnt->result), (int)SCpnt->result));
+/* See if the command completed normally, or whether something went wrong. */
+ memcpy(srp->header.sense_buffer, SCpnt->sense_buffer,
+ sizeof(SCpnt->sense_buffer));
+ switch (host_byte(SCpnt->result))
+ {
X case DID_OK:
- device->header.result = 0;
+ case DID_PASSTHROUGH: /* just guessing */
+ case DID_SOFT_ERROR: /* just guessing */
+ srp->header.result = 0;
X break;
X case DID_NO_CONNECT:
X case DID_BUS_BUSY:
X case DID_TIME_OUT:
- device->header.result = EBUSY;
+ srp->header.result = EBUSY;
X break;
X case DID_BAD_TARGET:
X case DID_ABORT:
X case DID_PARITY:
X case DID_RESET:
X case DID_BAD_INTR:
- device->header.result = EIO;
+ srp->header.result = EIO;
X break;
X case DID_ERROR:
- /*
- * There really should be DID_UNDERRUN and DID_OVERRUN error values,
+ /* There really should be DID_UNDERRUN and DID_OVERRUN error values,
X * and a means for callers of scsi_do_cmd to indicate whether an
X * underrun or overrun should signal an error. Until that can be
X * implemented, this kludge allows for returning useful error values
X * except in cases that return DID_ERROR that might be due to an
- * underrun.
- */
+ * underrun. [Underrun on advansys adapter yields DID_ABORT -dpg] */
X if (SCpnt->sense_buffer[0] == 0 &&
- status_byte(SCpnt->result) == GOOD)
- device->header.result = 0;
- else device->header.result = EIO;
+ status_byte(SCpnt->result) == GOOD)
+ srp->header.result = 0;
+ else
+ srp->header.result = EIO;
X break;
+ default:
+ SCSI_LOG_TIMEOUT(1, printk(
+ "sg: unexpected host_byte=%d, dev=%d in 'done'\n",
+ host_byte(SCpnt->result), dev));
+ srp->header.result = EIO;
+ break;
+ }
+
+/* Following if statement is a patch supplied by Eric Youngdale */
+ if (driver_byte(SCpnt->result) != 0
+ && (SCpnt->sense_buffer[0] & 0x7f) == 0x70
+ && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION
+ && sdp->device->removable) {
+/* Detected disc change. Set the bit - this may be used if there are */
+/* filesystems using this device. */
+ sdp->device->changed = 1;
X }
X
- /*
- * Now wake up the process that is waiting for the
- * result.
- */
- device->complete=1;
+/* Pick up error and status information */
+ srp->header.target_status = status_byte(SCpnt->result);
+ if ((sdp->sgdebug > 0) &&
+ ((CHECK_CONDITION == srp->header.target_status) ||
+ (COMMAND_TERMINATED == srp->header.target_status)))
+ print_sense("sg_command_done", SCpnt);
+ srp->header.host_status = host_byte(SCpnt->result);
+ srp->header.driver_status = driver_byte(SCpnt->result);
+
X scsi_release_command(SCpnt);
X SCpnt = NULL;
- wake_up(&scsi_generics[dev].read_wait);
+ if (sfp->closed) { /* whoops this fd already released, cleanup */
+ closed = 1;
+ SCSI_LOG_TIMEOUT(1,
+ printk("sg__done: already closed, freeing ...\n"));
+/* should check if module is unloaded <<<<<<< */
+ sg_sc_undo_rem(srp, NULL, 0);
+ if (NULL == sfp->headrp) {
+ SCSI_LOG_TIMEOUT(1,
+ printk("sg__done: already closed, final cleanup\n"));
+ sg_remove_sfp(sdp, sfp);
+ }
+ }
+/* Now wake up the process that is waiting for the result. */
+ /* A. Rubini says this is preferable+faster than wake_up() */
+ wake_up_interruptible(&sfp->read_wait);
+ if ((sfp->async_qp) && (! closed))
+ kill_fasync(sfp->async_qp, SIGPOLL);
X }
X
-static ssize_t sg_write(struct file *filp, const char *buf,
- size_t count, loff_t *ppos)
+static void sg_debug_all(const Sg_fd * sfp)
X {
- unsigned long flags;
- struct inode *inode = filp->f_dentry->d_inode;
- int bsize,size,amt,i;
- unsigned char cmnd[MAX_COMMAND_SIZE];
- kdev_t devt = inode->i_rdev;
- int dev = MINOR(devt);
- struct scsi_generic * device=&scsi_generics[dev];
- int input_size;
- unsigned char opcode;
- Scsi_Cmnd * SCpnt;
-
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if( !scsi_block_when_processing_errors(scsi_generics[dev].device) )
- {
- return -ENXIO;
- }
-
- if (ppos != &filp->f_pos) {
- /* FIXME: Hmm. Seek to the right place, or fail? */
- }
-
- if ((i=verify_area(VERIFY_READ,buf,count)))
- return i;
- /*
- * The minimum scsi command length is 6 bytes. If we get anything
- * less than this, it is clearly bogus.
- */
- if (count<(sizeof(struct sg_header) + 6))
- return -EIO;
-
- /*
- * If we still have a result pending from a previous command,
- * wait until the result has been read by the user before sending
- * another command.
- */
- while(device->pending)
- {
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
-#ifdef DEBUG
- printk("sg_write: sleeping on pending request\n");
+ const Sg_device * sdp = sg_dev_arr;
+ int k;
+
+ if (NULL == sg_dev_arr) {
+ printk("sg_debug_all: sg_dev_arr NULL, death is imminent\n");
+ return;
+ }
+ if (! sfp)
+ printk("sg_debug_all: sfp (file descriptor pointer) NULL\n");
+
+ printk("sg_debug_all: dev_max=%d, %s\n",
+ sg_template.dev_max, sg_version_str);
+ printk(" scsi_dma_free_sectors=%u, sg_pool_secs_aval=%d\n",
+ scsi_dma_free_sectors, sg_pool_secs_avail);
+ printk(" sg_big_buff=%d\n", sg_big_buff);
+#ifdef SG_DEBUG
+ printk(" malloc counts, kmallocs=%d, dma_pool=%d, pages=%d\n",
+ sg_num_kmal, sg_num_pool, sg_num_page);
X #endif
- interruptible_sleep_on(&device->write_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
-
- /*
- * Mark the device flags for the new state.
- */
- device->pending=1;
- device->complete=0;
- copy_from_user(&device->header,buf,sizeof(struct sg_header));
-
- device->header.pack_len=count;
- buf+=sizeof(struct sg_header);
-
- /*
- * Now we need to grab the command itself from the user's buffer.
- */
- get_user(opcode, buf);
- size=COMMAND_SIZE(opcode);
- if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
-
- /*
- * Determine buffer size.
- */
- input_size = device->header.pack_len - size;
- if( input_size > device->header.reply_len)
- {
- bsize = input_size;
- } else {
- bsize = device->header.reply_len;
+ for (k = 0; k < sg_template.dev_max; ++k, ++sdp) {
+ if (sdp->headfp) {
+ if (! sfp)
+ sfp = sdp->headfp; /* just to keep things going */
+ else if (sdp == sfp->parentdp)
+ printk(" ***** Invoking device follows *****\n");
+ sg_debug(sdp, sfp, 1);
+ }
X }
+}
X
- /*
- * Don't include the command header itself in the size.
- */
- bsize-=sizeof(struct sg_header);
- input_size-=sizeof(struct sg_header);
-
- /*
- * Verify that the user has actually passed enough bytes for this command.
- */
- if( input_size < 0 )
- {
- device->pending=0;
- wake_up( &device->write_wait );
- return -EIO;
- }
-
- /*
- * Allocate a buffer that is large enough to hold the data
- * that has been requested. Round up to an even number of sectors,
- * since scsi_malloc allocates in chunks of 512 bytes.
- */
- amt=bsize;
- if (!bsize)
- bsize++;
- bsize=(bsize+511) & ~511;
-
- /*
- * If we cannot allocate the buffer, report an error.
- */
- if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
- {
- device->pending=0;
- wake_up(&device->write_wait);
- return -ENOMEM;
+static void sg_debug(const Sg_device * sdp, const Sg_fd * sfp, int part_of)
+{
+ Sg_fd * fp;
+ Sg_request * srp;
+ int dev;
+ int k;
+
+ if (! sfp)
+ printk("sg_debug: sfp (file descriptor pointer) NULL\n");
+ if (! sdp) {
+ printk("sg_debug: sdp pointer (to device) NULL\n");
+ return;
X }
-
-#ifdef DEBUG
- printk("allocating device\n");
-#endif
-
- /*
- * Grab a device pointer for the device we want to talk to. If we
- * don't want to block, just return with the appropriate message.
- */
- if (!(SCpnt=scsi_allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
- {
- device->pending=0;
- wake_up(&device->write_wait);
- sg_free(device->buff,device->buff_len);
- device->buff = NULL;
- return -EAGAIN;
+ else if (! sdp->device) {
+ printk("sg_debug: device detached ??\n");
+ return;
X }
-#ifdef DEBUG
- printk("device allocated\n");
-#endif
-
- SCpnt->request.rq_dev = devt;
- SCpnt->request.rq_status = RQ_ACTIVE;
- SCpnt->sense_buffer[0]=0;
- SCpnt->cmd_len = size;
-
- /*
- * Now copy the SCSI command from the user's address space.
- */
- copy_from_user(cmnd,buf,size);
- buf+=size;
-
- /*
- * If we are writing data, copy the data we are writing. The pack_len
- * field also includes the length of the header and the command,
- * so we need to subtract these off.
- */
- if (input_size > 0) copy_from_user(device->buff, buf, input_size);
-
- /*
- * Set the LUN field in the command structure.
- */
- cmnd[1]= (cmnd[1] & 0x1f) | (device->device->lun<<5);
-
-#ifdef DEBUG
- printk("do cmd\n");
-#endif
-
- /*
- * Now pass the actual command down to the low-level driver. We
- * do not do any more here - when the interrupt arrives, we will
- * then do the post-processing.
- */
- spin_lock_irqsave(&io_request_lock, flags);
- scsi_do_cmd (SCpnt,(void *) cmnd,
- (void *) device->buff,amt,
- sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ dev = MINOR(sdp->i_rdev);
X
-#ifdef DEBUG
- printk("done cmd\n");
+ if (part_of)
+ printk(" >>> device=%d(sg%c), ", dev, 'a' + dev);
+ else
+ printk("sg_debug: device=%d(sg%c), ", dev, 'a' + dev);
+ printk("scsi%d chan=%d id=%d lun=%d em=%d\n", sdp->device->host->host_no,
+ sdp->device->channel, sdp->device->id, sdp->device->lun,
+ sdp->device->host->hostt->emulated);
+ printk(" sg_tablesize=%d, excl=%d, sgdebug=%d, merge_fd=%d\n",
+ sdp->sg_tablesize, sdp->exclude, sdp->sgdebug, sdp->merge_fd);
+ if (! part_of) {
+ printk(" scsi_dma_free_sectors=%u, sg_pool_secs_aval=%d\n",
+ scsi_dma_free_sectors, sg_pool_secs_avail);
+#ifdef SG_DEBUG
+ printk(" mallocs: kmallocs=%d, dma_pool=%d, pages=%d\n",
+ sg_num_kmal, sg_num_pool, sg_num_page);
X #endif
+ }
X
- return count;
-}
-
-static unsigned int sg_poll(struct file *file, poll_table * wait)
-{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
- struct scsi_generic *device = &scsi_generics[dev];
- unsigned int mask = 0;
-
- poll_wait(file, &scsi_generics[dev].read_wait, wait);
- poll_wait(file, &scsi_generics[dev].write_wait, wait);
- if(device->pending && device->complete)
- mask |= POLLIN | POLLRDNORM;
- if(!device->pending)
- mask |= POLLOUT | POLLWRNORM;
-
- return mask;
+ fp = sdp->headfp;
+ for (k = 1; fp; fp = fp->nextfp, ++k) {
+ if (sfp == fp)
+ printk(" *** Following data belongs to invoking FD ***\n");
+ else if (! fp->parentdp)
+ printk(">> Following FD has NULL parent pointer ???\n");
+ printk(" FD(%d): timeout=%d, fb_size=%d, cmd_q=%d\n",
+ k, fp->timeout, fp->fb_size, (int)fp->cmd_q);
+ printk(" low_dma=%d, force_packid=%d, closed=%d\n",
+ (int)fp->low_dma, (int)fp->force_packid, (int)fp->closed);
+ srp = fp->headrp;
+ if (NULL == srp)
+ printk(" No requests active\n");
+ while (srp) {
+ if (srp->fb_used)
+ printk("using 1st buff >> ");
+ else
+ printk(" ");
+ if (srp->my_cmdp)
+ printk("written: pack_id=%d, bufflen=%d, use_sg=%d\n",
+ srp->header.pack_id, srp->my_cmdp->bufflen,
+ srp->my_cmdp->use_sg);
+ else
+ printk("to_read: pack_id=%d, bufflen=%d, use_sg=%d\n",
+ srp->header.pack_id, srp->data.bufflen, srp->data.use_sg);
+ if (! srp->parentfp)
+ printk(">> request has NULL parent pointer ???\n");
+ srp = srp->nextrp;
+ }
+ }
X }
X
X static struct file_operations sg_fops = {
@@ -574,24 +920,30 @@
X sg_ioctl, /* ioctl */
X NULL, /* mmap */
X sg_open, /* open */
- NULL, /* flush */
- sg_close, /* release */
- NULL /* fsync */
+ NULL, /* flush */
+ sg_release, /* release, was formerly sg_close */
+ NULL, /* fsync */
+ sg_fasync, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL, /* lock */
X };
X
X
-static int sg_detect(Scsi_Device * SDp){
-
- switch (SDp->type) {
- case TYPE_DISK:
- case TYPE_MOD:
- case TYPE_ROM:
- case TYPE_WORM:
- case TYPE_TAPE: break;
- default:
- printk("Detected scsi generic sg%c at scsi%d, channel %d, id %d, lun %d\n",
- 'a'+sg_template.dev_noticed,
- SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
+static int sg_detect(Scsi_Device * scsidp)
+{
+ switch (scsidp->type) {
+ case TYPE_DISK:
+ case TYPE_MOD:
+ case TYPE_ROM:
+ case TYPE_WORM:
+ case TYPE_TAPE: break;
+ default:
+ printk("Detected scsi generic sg%c at scsi%d,"
+ " channel %d, id %d, lun %d\n",
+ 'a'+sg_template.dev_noticed,
+ scsidp->host->host_no, scsidp->channel,
+ scsidp->id, scsidp->lun);
X }
X sg_template.dev_noticed++;
X return 1;
@@ -605,84 +957,108 @@
X if (sg_template.dev_noticed == 0) return 0;
X
X if(!sg_registered) {
- if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
- {
- printk("Unable to get major %d for generic SCSI device\n",
- SCSI_GENERIC_MAJOR);
- return 1;
- }
- sg_registered++;
+ if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
+ {
+ printk("Unable to get major %d for generic SCSI device\n",
+ SCSI_GENERIC_MAJOR);
+ return 1;
+ }
+ sg_registered++;
X }
X
X /* If we have already been through here, return */
- if(scsi_generics) return 0;
-
-#ifdef DEBUG
- printk("sg: Init generic device.\n");
-#endif
-
-#ifdef SG_BIG_BUFF
- big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF, GFP_ATOMIC | GFP_DMA);
-#endif
-
- scsi_generics = (struct scsi_generic *)
- scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
- * sizeof(struct scsi_generic), GFP_ATOMIC);
- memset(scsi_generics, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
- * sizeof(struct scsi_generic));
+ if(sg_dev_arr) return 0;
X
+ SCSI_LOG_TIMEOUT(3, printk("sg_init\n"));
+ sg_dev_arr = (Sg_device *)
+ scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
+ * sizeof(Sg_device), GFP_ATOMIC);
+ if (NULL == sg_dev_arr) {
+ printk("sg_init: no space for sg_dev_arr\n");
+ return 1;
+ }
X sg_template.dev_max = sg_template.dev_noticed + SG_EXTRA_DEVS;


X return 0;
X }
X

-static int sg_attach(Scsi_Device * SDp)
+static int sg_attach(Scsi_Device * scsidp)
X {
- struct scsi_generic * gpnt;
- int i;
+ Sg_device * sdp = sg_dev_arr;
+ int k;
X
- if(sg_template.nr_dev >= sg_template.dev_max)
+ if ((sg_template.nr_dev >= sg_template.dev_max) || (! sdp))
X {
- SDp->attached--;
- return 1;
+ scsidp->attached--;
+ return 1;
X }
X
- for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
- if(!gpnt->device) break;
+ for(k = 0; k < sg_template.dev_max; k++, sdp++)
+ if(! sdp->device) break;
X
- if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
+ if(k >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
X
- scsi_generics[i].device=SDp;
- scsi_generics[i].users=0;
- scsi_generics[i].generic_wait=NULL;
- scsi_generics[i].read_wait=NULL;
- scsi_generics[i].write_wait=NULL;
- scsi_generics[i].buff=NULL;
- scsi_generics[i].exclude=0;
- scsi_generics[i].pending=0;
- scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT;
+ SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k));
+ sdp->device = scsidp;
+ sdp->generic_wait = NULL;
+ sdp->headfp= NULL;
+ sdp->exclude = 0;
+ sdp->merge_fd = 0;
+ sdp->sgdebug = 0;
+ sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
+ sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
X sg_template.nr_dev++;
X return 0;
-};
-
-
+}
X
-static void sg_detach(Scsi_Device * SDp)
+/* Called at 'finish' of init process, after all attaches */
+static void sg_finish(void)
X {
- struct scsi_generic * gpnt;
- int i;
+ SCSI_LOG_TIMEOUT(3, printk("sg_finish: dma_free_sectors=%u\n",
+ scsi_dma_free_sectors));
+}
X
- for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
- if(gpnt->device == SDp) {
- gpnt->device = NULL;
- SDp->attached--;
- sg_template.nr_dev--;
- /*
- * avoid associated device /dev/sg? bying incremented
- * each time module is inserted/removed , <d...@lectra.fr>
- */
- sg_template.dev_noticed--;
- return;
- }
+static void sg_detach(Scsi_Device * scsidp)
+{
+ Sg_device * sdp = sg_dev_arr;
+ unsigned long flags = 0;
+ Sg_fd * sfp;
+ Sg_request * srp;
+ int k;
+
+ if (NULL == sdp) return; /* all is not well ... */
+ for (k = 0; k < sg_template.dev_max; k++, sdp++) {
+ if(sdp->device != scsidp)
+ continue; /* dirty but lowers nesting */
+ if (sdp->headfp) {
+/* Need to stop sg_command_done() playing with this list during this loop */
+ spin_lock_irqsave(&io_request_lock, flags);
+ sfp = sdp->headfp;
+ while (sfp) {
+ srp = sfp->headrp;
+ while (srp) {
+ if (srp->my_cmdp)
+ sg_shorten_timeout(srp->my_cmdp);
+ srp = srp->nextrp;
+ }
+ sfp = sfp->nextfp;
+ }
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty, sleep(3)\n", k));
+ scsi_sleep(3); /* sleep 3 jiffies, hoping for timeout to go off */
+ }
+ else {
+ SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k));
+ sdp->device = NULL;
+ }
+ scsidp->attached--;
+ sg_template.nr_dev--;
+ /*
+ * avoid associated device /dev/sg? bying incremented
+ * each time module is inserted/removed , <d...@lectra.fr>
+ */
+ sg_template.dev_noticed--;
+ return;
+ }
X return;
X }
X
@@ -698,34 +1074,555 @@
X scsi_unregister_module(MODULE_SCSI_DEV, &sg_template);
X unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
X
- if(scsi_generics != NULL) {
- scsi_init_free((char *) scsi_generics,
- (sg_template.dev_noticed + SG_EXTRA_DEVS)
- * sizeof(struct scsi_generic));
+ if(sg_dev_arr != NULL) {
+/* Really worrying situation of writes still pending and get here */
+/* Strategy: shorten timeout on release + wait on detach ... */
+ scsi_init_free((char *) sg_dev_arr,
+ (sg_template.dev_noticed + SG_EXTRA_DEVS)
+ * sizeof(Sg_device));
+ sg_dev_arr = NULL;
X }
X sg_template.dev_max = 0;
-#ifdef SG_BIG_BUFF
- if(big_buff != NULL)
- scsi_init_free(big_buff, SG_BIG_BUFF);
-#endif
X }
X #endif /* MODULE */
X
-/*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
+
+#if 0
+extern void scsi_times_out (Scsi_Cmnd * SCpnt);
+extern void scsi_old_times_out (Scsi_Cmnd * SCpnt);
+#endif
+
+/* Can't see clean way to abort a command so shorten timeout to 1 jiffy */
+static void sg_shorten_timeout(Scsi_Cmnd * scpnt)
+{
+#if 0 /* scsi_syms.c is very miserly about exported functions */
+ scsi_delete_timer(scpnt);
+ if (! scpnt)
+ return;
+ scpnt->timeout_per_command = 1; /* try 1 jiffy (perhaps 0 jiffies) */
+ if (scpnt->host->hostt->use_new_eh_code)
+ scsi_add_timer(scpnt, scpnt->timeout_per_command, scsi_times_out);
+ else
+ scsi_add_timer(scpnt, scpnt->timeout_per_command,
+ scsi_old_times_out);
+#else
+ scsi_sleep(HZ); /* just sleep 1 second and hope ... */
+#endif
+}
+
+static int sg_sc_build(Sg_request * srp, int max_buff_size,
+ const char * inp, int num_write_xfer)
+{
+ int ret_sz, mem_src;
+ int blk_size = max_buff_size;
+ char * p = NULL;
+
+ if ((blk_size < 0) || (! srp))
+ return -EFAULT;
+
+ SCSI_LOG_TIMEOUT(4, printk("sg build: m_b_s=%d, num_write_xfer=%d\n",
+ max_buff_size, num_write_xfer));
+ if (0 == blk_size)
+ ++blk_size; /* don't know why */
+/* round request up to next highest SG_SECTOR_SZ byte boundary */
+ blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
+ SCSI_LOG_TIMEOUT(5, printk("sg_sc_build: blk_size=%d\n", blk_size));
+
+ if (blk_size <= SG_SCATTER_SZ) {
+ mem_src = SG_HEAP_FB;
+ p = sg_malloc(srp, blk_size, &ret_sz, &mem_src);
+ if (! p)
+ return -ENOMEM;
+ if (blk_size == ret_sz) { /* got it on the first attempt */
+ srp->data.buffer = p;
+ srp->data.bufflen = blk_size;
+ srp->data.mem_src = mem_src;
+ srp->data.b_malloc_len = blk_size;
+ if (inp && (num_write_xfer > 0))
+ copy_from_user(srp->data.buffer, inp, num_write_xfer);


+ return 0;
+ }
+ }

+ else {
+ mem_src = SG_HEAP_PAGE;
+ p = sg_malloc(srp, SG_SCATTER_SZ, &ret_sz, &mem_src);
+ if (! p)
+ return -ENOMEM;
+ }
+/* Want some local declarations, so start new block ... */
+ { /* lets try and build a scatter gather list */
+ struct scatterlist * sclp;
+ int k, rem_sz, num, nxt;
+ int sc_bufflen = PAGE_SIZE;
+ int mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
+ int sg_tablesize = srp->parentfp->parentdp->sg_tablesize;
+ int first = 1;
+
+ k = SG_HEAP_KMAL; /* want to protect mem_src, use k as scratch */
+ srp->data.buffer = (struct scatterlist *)sg_malloc(srp,
+ sc_bufflen, &num, &k);
+ srp->data.mem_src = (char)k;
+ /* N.B. ret_sz and mem_src carried into this block ... */
+ if (! srp->data.buffer)
+ return -ENOMEM;
+ else if (num != sc_bufflen) {
+ sc_bufflen = num;
+ mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
+ }
+ srp->data.sglist_len = sc_bufflen;
+ memset(srp->data.buffer, 0, sc_bufflen);
+ for (k = 0, sclp = srp->data.buffer, rem_sz = blk_size, nxt =0;
+ (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems);
+ ++k, rem_sz -= ret_sz, ++sclp) {
+ if (first)
+ first = 0;
+ else {
+ num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
+ mem_src = SG_HEAP_PAGE;
+ p = sg_malloc(srp, num, &ret_sz, &mem_src);
+ if (! p)
+ break;
+ }
+ sclp->address = p;
+ sclp->length = ret_sz;
+ sclp->alt_address = (char *)mem_src;
+
+ if(inp && (num_write_xfer > 0)) {
+ num = (ret_sz > num_write_xfer) ? num_write_xfer : ret_sz;
+ copy_from_user(sclp->address, inp, num);
+ num_write_xfer -= num;
+ inp += num;
+ }
+ SCSI_LOG_TIMEOUT(5,
+ printk("sg_sc_build: k=%d, a=0x%x, len=%d, ms=%d\n",
+ k, (int)sclp->address, ret_sz, (int)sclp->alt_address));
+ } /* end of for loop */
+ srp->data.use_sg = k;
+ SCSI_LOG_TIMEOUT(5,
+ printk("sg_sc_build: use_sg=%d, rem_sz=%d\n", k, rem_sz));
+ srp->data.bufflen = blk_size;
+ if (rem_sz > 0) /* must have failed */
+ return -ENOMEM;
+ }


+ return 0;
+}
+

+static int sg_sc_undo_rem(Sg_request * srp, char * outp,
+ int num_read_xfer)
+{
+ if (! srp)
+ return -EFAULT;
+ SCSI_LOG_TIMEOUT(4, printk("sg_sc_undo_rem: num_read_xfer=%d\n",
+ num_read_xfer));
+ if (! outp)
+ num_read_xfer = 0;
+ if(srp->data.use_sg) {
+ int k, num, mem_src;
+ struct scatterlist * sclp = (struct scatterlist *)srp->data.buffer;
+
+ for (k = 0; (k < srp->data.use_sg) && sclp->address; ++k, ++sclp) {
+ if (num_read_xfer > 0) {
+ num = (int)sclp->length;
+ if (num > num_read_xfer) {
+ copy_to_user(outp, sclp->address, num_read_xfer);
+ outp += num_read_xfer;
+ num_read_xfer = 0;
+ }
+ else {
+ copy_to_user(outp, sclp->address, num);
+ outp += num;
+ num_read_xfer -= num;
+ }
+ }
+ mem_src = (int)sclp->alt_address;
+ SCSI_LOG_TIMEOUT(5,
+ printk("sg_sc_undo_rem: k=%d, a=0x%x, len=%d, ms=%d\n",
+ k, (int)sclp->address, sclp->length, mem_src));
+ sg_free(srp, sclp->address, sclp->length, mem_src);
+ }
+ sg_free(srp, srp->data.buffer, srp->data.sglist_len,
+ srp->data.mem_src);
+ }
+ else {
+ if (num_read_xfer > 0)
+ copy_to_user(outp, srp->data.buffer, num_read_xfer);
+ sg_free(srp, srp->data.buffer, srp->data.b_malloc_len,
+ srp->data.mem_src);
+ }
+ if (0 == sg_remove_request(srp->parentfp, srp)) {
+ SCSI_LOG_TIMEOUT(1, printk("sg_sc_undo_rem: srp=%d not found\n",
+ (int)srp));
+ }


+ return 0;
+}
+

+static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id)
+{
+ Sg_request * resp = NULL;
+
+ resp = sfp->headrp;
+ while (resp) {
+ if ((! resp->my_cmdp) &&
+ ((-1 == pack_id) || (resp->header.pack_id == pack_id)))
+ return resp;
+ resp = resp->nextrp;
+ }
+ return resp;
+}
+
+/* always adds to end of list */
+static Sg_request * sg_add_request(Sg_fd * sfp)
+{
+ int k;
+ Sg_request * resp = NULL;
+ Sg_request * rp;
+
+ resp = sfp->headrp;
+ rp = sfp->req_arr;
+ if (! resp) {
+ resp = rp;
+ sfp->headrp = resp;
+ }
+ else {
+ if (0 == sfp->cmd_q)
+ resp = NULL; /* command queuing disallowed */
+ else {
+ for (k = 0, rp; k < SG_MAX_QUEUE; ++k, ++rp) {
+ if (! rp->parentfp)
+ break;
+ }
+ if (k < SG_MAX_QUEUE) {
+ while (resp->nextrp) resp = resp->nextrp;
+ resp->nextrp = rp;
+ resp = rp;
+ }
+ else
+ resp = NULL;
+ }
+ }
+ if (resp) {
+ resp->parentfp = sfp;
+ resp->nextrp = NULL;
+ resp->fb_used = 0;
+ memset(&resp->data, 0, sizeof(Sg_scatter_hold));
+ memset(&resp->header, 0, sizeof(struct sg_header));
+ resp->my_cmdp = NULL;
+ }
+ return resp;
+}
+
+/* Return of 1 for found; 0 for not found */
+static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp)
+{
+ Sg_request * prev_rp;
+ Sg_request * rp;
+
+ if ((! sfp) || (! srp) || (! sfp->headrp))
+ return 0;
+ prev_rp = sfp->headrp;
+ if (srp == prev_rp) {
+ prev_rp->parentfp = NULL;
+ sfp->headrp = prev_rp->nextrp;
+ return 1;
+ }
+ while ((rp = prev_rp->nextrp)) {
+ if (srp == rp) {
+ rp->parentfp = NULL;
+ prev_rp->nextrp = rp->nextrp;
+ return 1;
+ }
+ prev_rp = rp;
+ }


+ return 0;
+}
+

+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev)
+{
+ Sg_fd * sfp;
+
+ if (sdp->merge_fd) {
+ ++sdp->merge_fd;
+ return sdp->headfp;
+ }
+ sfp = (Sg_fd *)sg_low_malloc(sizeof(Sg_fd), 0, SG_HEAP_KMAL, 0);
+ if (sfp) {
+ memset(sfp, 0, sizeof(Sg_fd));
+ sfp->my_mem_src = SG_HEAP_KMAL;
+ }
+ else
+ return NULL;
+
+ sfp->timeout = SG_DEFAULT_TIMEOUT;
+ sfp->force_packid = SG_DEF_FORCE_PACK_ID;
+ sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ?
+ sdp->device->host->unchecked_isa_dma : 1;
+ sfp->cmd_q = SG_DEF_COMMAND_Q;
+ sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, sfp->low_dma,
+ SG_HEAP_PAGE, &sfp->fb_size);
+ if (! sfp->fst_buf)
+ sfp->fb_size = 0;
+ sfp->parentdp = sdp;
+ if (! sdp->headfp)
+ sdp->headfp = sfp;
+ else { /* add to tail of existing list */
+ Sg_fd * pfp = sdp->headfp;
+ while (pfp->nextfp)
+ pfp = pfp->nextfp;
+ pfp->nextfp = sfp;
+ }
+ sg_big_buff = sfp->fb_size; /* show sysctl most recent "fb" size */
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%x, m_s=%d\n",
+ (int)sfp, (int)sfp->my_mem_src));
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: fb_sz=%d, fst_buf=0x%x\n",
+ sfp->fb_size, (int)sfp->fst_buf));
+ return sfp;
+}
+
+static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
+{
+ Sg_request * srp;
+ Sg_request * tsrp;
+ int dirty = 0;
+ int res = 0;
+
+ if (sdp->merge_fd) {
+ if (--sdp->merge_fd)
+ return 0; /* if merge_fd then dec merge_fd counter */
+ }
+ srp = sfp->headrp;
+ if (srp) {
+/* Need to stop sg_command_done() playing with this list during this loop */
+ while (srp) {
+ tsrp = srp->nextrp;
+ if (! srp->my_cmdp)
+ sg_sc_undo_rem(srp, NULL, 0);
+ else
+ ++dirty;
+ srp = tsrp;
+ }
+ }
+ if (0 == dirty) {
+ Sg_fd * fp;
+ Sg_fd * prev_fp = sdp->headfp;
+
+ if (sfp == prev_fp)
+ sdp->headfp = prev_fp->nextfp;
+ else {
+ while ((fp = prev_fp->nextfp)) {
+ if (sfp == fp) {
+ prev_fp->nextfp = fp->nextfp;
+ break;
+ }
+ prev_fp = fp;
+ }
+ }
+SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: fb_sz=%d, fst_buf=0x%x\n",
+ sfp->fb_size, (int)sfp->fst_buf));
+ sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
+ sfp->parentdp = NULL;
+ sfp->fst_buf = NULL;
+ sfp->fb_size = 0;
+ SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%x\n", (int)sfp));
+ sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->my_mem_src);
+ res = 1;
+ }
+ else {
+ sfp->closed = 1; /* flag dirty state on this fd */
+ SCSI_LOG_TIMEOUT(1, printk(
+ "sg_remove_sfp: worrisome, %d writes pending\n", dirty));
+ }
+ return res;
+}
+
+static int sg_fb_in_use(const Sg_fd * sfp)
+{
+ const Sg_request * srp = sfp->headrp;
+
+ while (srp) {
+ if (srp->fb_used)
+ return 1;
+ srp = srp->nextrp;
+ }


+ return 0;
+}
+

+/* If retSzp==NULL want exact size or fail */
+/* sg_low_malloc() should always be called from a process context allowing
+ GFP_KERNEL to be used instead of GFP_ATOMIC */
+static char * sg_low_malloc(int rqSz, int lowDma, int mem_src, int * retSzp)
+{
+ char * resp = NULL;
+ int page_mask = lowDma ? (GFP_KERNEL | GFP_DMA) : GFP_KERNEL;
+
+ if (rqSz <= 0)
+ return resp;
+ if (SG_HEAP_KMAL == mem_src) {
+ page_mask = lowDma ? (GFP_ATOMIC | GFP_DMA) : GFP_ATOMIC;
+ /* Seen kmalloc(..,GFP_KERNEL) hang for 40 secs! */
+ resp = kmalloc(rqSz, page_mask);
+ if (resp && retSzp) *retSzp = rqSz;
+#ifdef SG_DEBUG
+ if (resp) ++sg_num_kmal;
+#endif
+ return resp;
+ }
+ if (SG_HEAP_POOL == mem_src) {
+ int num_sect = rqSz / SG_SECTOR_SZ;
+
+ if (0 != (rqSz & SG_SECTOR_MSK)) {
+ if (! retSzp)
+ return resp;
+ ++num_sect;
+ rqSz = num_sect * SG_SECTOR_SZ;
+ }
+ while (num_sect > 0) {
+ if ((num_sect <= sg_pool_secs_avail) &&
+ (scsi_dma_free_sectors > (SG_LOW_POOL_THRESHHOLD + num_sect))) {
+ resp = scsi_malloc(rqSz);
+ if (resp) {
+ if (retSzp) *retSzp = rqSz;
+ sg_pool_secs_avail -= num_sect;
+#ifdef SG_DEBUG
+ ++sg_num_pool;
+#endif
+ return resp;
+ }
+ }
+ if (! retSzp)
+ return resp;
+ num_sect /= 2; /* try half as many */
+ rqSz = num_sect * SG_SECTOR_SZ;
+ }
+ }
+ else if (SG_HEAP_PAGE == mem_src) {
+ int order, a_size;
+ int resSz = rqSz;
+
+ for (order = 0, a_size = PAGE_SIZE;
+ a_size < rqSz; order++, a_size <<= 1)
+ ;
+ resp = (char *)__get_free_pages(page_mask, order);
+ while ((! resp) && order && retSzp) {
+ --order;
+ a_size >>= 1; /* divide by 2, until PAGE_SIZE */
+ resp = (char *)__get_free_pages(page_mask, order); /* try half */
+ resSz = a_size;
+ }
+ if (retSzp) *retSzp = resSz;
+#ifdef SG_DEBUG
+ if (resp) ++sg_num_page;
+#endif
+ }
+ else
+ printk("sg_low_malloc: bad mem_src=%d, rqSz=%df\n", mem_src, rqSz);
+ return resp;
+}
+
+static char * sg_malloc(Sg_request * srp, int size, int * retSzp,
+ int * mem_srcp)
+{
+ char * resp = NULL;
+
+ if (retSzp) *retSzp = size;
+ if (size <= 0)
+ ;
+ else {
+ Sg_fd * sfp = srp->parentfp;
+ int low_dma = sfp->low_dma;
+ int l_ms = -1; /* invalid value */
+
+ switch (*mem_srcp)
+ {
+ case SG_HEAP_PAGE:
+ case SG_HEAP_FB:
+ l_ms = (size < PAGE_SIZE) ? SG_HEAP_POOL : SG_HEAP_PAGE;
+ resp = sg_low_malloc(size, low_dma, l_ms, 0);
+ if (resp)
+ break;
+ if ((size <= sfp->fb_size) && (0 == sg_fb_in_use(sfp))) {
+ SCSI_LOG_TIMEOUT(6,
+ printk("sg_malloc: scsi_malloc failed, get fst_buf\n"));
+ resp = sfp->fst_buf;
+ srp->fb_used = 1;
+ l_ms = SG_HEAP_FB;
+ break;
+ }
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ if (! resp) {
+ l_ms = (SG_HEAP_POOL == l_ms) ? SG_HEAP_PAGE : SG_HEAP_POOL;
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ if (! resp) {
+ l_ms = SG_HEAP_KMAL;
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ }
+ }
+ if (resp && retSzp) *retSzp = size;
+ break;
+ case SG_HEAP_KMAL:
+ l_ms = SG_HEAP_PAGE;
+ resp = sg_low_malloc(size, low_dma, l_ms, 0);
+ if (resp)
+ break;
+ l_ms = SG_HEAP_POOL;
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ if (resp && retSzp) *retSzp = size;
+ break;
+ default:
+ SCSI_LOG_TIMEOUT(1, printk("sg_malloc: bad ms=%d\n", *mem_srcp));
+ break;
+ }
+ if (resp) *mem_srcp = l_ms;
+ }
+ SCSI_LOG_TIMEOUT(6, printk("sg_malloc: size=%d, ms=%d, ret=0x%x\n",
+ size, *mem_srcp, (int)resp));
+ return resp;
+}
+
+static void sg_low_free(char * buff, int size, int mem_src)
+{
+ if (! buff)
+ return;
+ if (SG_HEAP_POOL == mem_src) {
+ int num_sect = size / SG_SECTOR_SZ;
+ scsi_free(buff, size);
+ sg_pool_secs_avail += num_sect;
+ }
+ else if (SG_HEAP_KMAL == mem_src)
+ kfree(buff); /* size not used */
+ else if (SG_HEAP_PAGE == mem_src) {
+ int order, a_size;
+
+ for (order = 0, a_size = PAGE_SIZE;
+ a_size < size; order++, a_size <<= 1)
+ ;
+ free_pages((unsigned long)buff, order);
+ }
+ else
+ printk("sg_low_free: bad mem_src=%d, buff=0x%x, rqSz=%df\n",
+ mem_src, (int)buff, size);
+}
+
+static void sg_free(Sg_request * srp, char * buff, int size, int mem_src)
+{
+ Sg_fd * sfp = srp->parentfp;
+
+ SCSI_LOG_TIMEOUT(6,
+ printk("sg_free: buff=0x%x, size=%d\n", (int)buff, size));
+ if ((! sfp) || (! buff) || (size <= 0))
+ ;
+ else if (sfp->fst_buf == buff) {
+ srp->fb_used = 0;
+ SCSI_LOG_TIMEOUT(6, printk("sg_free: left cause fst_buf\n"));
+ }
+ else
+ sg_low_free(buff, size, mem_src);
+}
+
+static void sg_clr_scpnt(Scsi_Cmnd * SCpnt)
+{
+ SCpnt->use_sg = 0;
+ SCpnt->sglist_len = 0;
+ SCpnt->bufflen = 0;
+ SCpnt->buffer = NULL;
+}
+
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.2.5/linux/drivers/scsi/sym53c8xx.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx.c Mon Apr 12 09:51:04 1999
@@ -0,0 +1,11768 @@
+/******************************************************************************
+** High Performance device driver for the Symbios 53C896 controller.
+**
+** Copyright (C) 1998 Gerard Roudier <grou...@club-internet.fr>
+**
+** This driver also supports all the Symbios 53C8XX controller family,
+** except 53C810 revisions < 16, 53C825 revisions < 16 and all
+** revisions of 53C815 controllers.
+**
+** This driver is based on the Linux port of the FreeBSD ncr driver.
+**
+** Copyright (C) 1994 Wolfgang Stanglmeier
+**
+**-----------------------------------------------------------------------------
+**
+** 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.
+**
+**-----------------------------------------------------------------------------
+**
+** The Linux port of the FreeBSD ncr driver has been achieved in
+** november 1995 by:
+**
+** Gerard Roudier <grou...@club-internet.fr>
+**
+** Being given that this driver originates from the FreeBSD version, and
+** in order to keep synergy on both, any suggested enhancements and corrections
+** received on Linux are automatically a potential candidate for the FreeBSD
+** version.
+**
+** The original driver has been written for 386bsd and FreeBSD by
+** Wolfgang Stanglmeier <wo...@cologne.de>
+** Stefan Esser <s...@mi.Uni-Koeln.de>
+**
+**-----------------------------------------------------------------------------
+**
+** Major contributions:
+** --------------------
+**
+** NVRAM detection and reading.
+** Copyright (C) 1997 Richard Waltham <dorm...@farsrobt.demon.co.uk>
+**
+*******************************************************************************
+*/
+
+/*
+** April 2 1999, sym53c8xx version 1.3c
+**
+** Supported SCSI features:
+** Synchronous data transfers
+** Wide16 SCSI BUS
+** Disconnection/Reselection
+** Tagged command queuing
+** SCSI Parity checking
+**
+** Supported NCR chips:
+** 53C810A (8 bits, Fast 10, no rom BIOS)
+** 53C825A (Wide, Fast 10, on-board rom BIOS)
+** 53C860 (8 bits, Fast 20, no rom BIOS)
+** 53C875 (Wide, Fast 20, on-board rom BIOS)
+** 53C876 (Wide, Fast 20 Dual, on-board rom BIOS)
+** 53C895 (Wide, Fast 40, on-board rom BIOS)
+** 53C896 (Wide, Fast 40 Dual, on-board rom BIOS)
+**
+** Other features:
+** Memory mapped IO
+** Module
+** Shared IRQ
+*/
+


+/*
+** Name and version of the driver
+*/

+#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.3c"
+
+/* #define DEBUG_896R1 */
+#define SCSI_NCR_OPTIMIZE_896
+/* #define SCSI_NCR_OPTIMIZE_896_1 */
+
+#define SCSI_NCR_DEBUG_FLAGS (0)
+
+#define NAME53C "sym53c"
+#define NAME53C8XX "sym53c8xx"
+
+/*==========================================================
+**
+** Include files
+**
+**==========================================================
+*/
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+#include <asm/spinlock.h>
+#endif
+#include <linux/delay.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/stat.h>
+
+#include <linux/version.h>
+#include <linux/blk.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35)
+#include <linux/init.h>
+#else
+#ifndef __initdata
+#define __initdata
+#endif
+#ifndef __initfunc
+#define __initfunc(__arginit) __arginit
+#endif
+#endif
+
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+#include <linux/bios32.h>
+#endif
+
+#include "scsi.h"
+#include "hosts.h"
+#include "constants.h"
+#include "sd.h"
+
+#include <linux/types.h>
+
+/*
+** Define BITS_PER_LONG for earlier linux versions.
+*/
+#ifndef BITS_PER_LONG
+#if (~0UL) == 0xffffffffUL
+#define BITS_PER_LONG 32
+#else
+#define BITS_PER_LONG 64
+#endif
+#endif
+
+/*
+** Define the BSD style u_int32 and u_int64 type.
+** Are in fact u_int32_t and u_int64_t :-)
+*/
+typedef u32 u_int32;
+typedef u64 u_int64;
+
+#include "sym53c8xx.h"
+
+/*==========================================================
+**
+** A la VMS/CAM-3 queue management.
+** Implemented from linux list management.
+**
+**==========================================================
+*/
+
+typedef struct xpt_quehead {
+ struct xpt_quehead *flink; /* Forward pointer */
+ struct xpt_quehead *blink; /* Backward pointer */
+} XPT_QUEHEAD;
+
+#define xpt_que_init(ptr) do { \
+ (ptr)->flink = (ptr); (ptr)->blink = (ptr); \
+} while (0)
+
+static inline void __xpt_que_add(struct xpt_quehead * new,
+ struct xpt_quehead * blink,
+ struct xpt_quehead * flink)
+{
+ flink->blink = new;
+ new->flink = flink;
+ new->blink = blink;
+ blink->flink = new;
+}
+
+static inline void __xpt_que_del(struct xpt_quehead * blink,
+ struct xpt_quehead * flink)
+{
+ flink->blink = blink;
+ blink->flink = flink;
+}
+
+static inline int xpt_que_empty(struct xpt_quehead *head)
+{
+ return head->flink == head;
+}
+
+static inline void xpt_que_splice(struct xpt_quehead *list,
+ struct xpt_quehead *head)
+{
+ struct xpt_quehead *first = list->flink;
+
+ if (first != list) {
+ struct xpt_quehead *last = list->blink;
+ struct xpt_quehead *at = head->flink;
+
+ first->blink = head;
+ head->flink = first;
+
+ last->flink = at;
+ at->blink = last;
+ }
+}
+
+#define xpt_que_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+
+#define xpt_insque(new, pos) __xpt_que_add(new, pos, (pos)->flink)
+
+#define xpt_remque(el) __xpt_que_del((el)->blink, (el)->flink)
+
+#define xpt_insque_head(new, head) __xpt_que_add(new, head, (head)->flink)
+
+static inline struct xpt_quehead *xpt_remque_head(struct xpt_quehead *head)
+{
+ struct xpt_quehead *elem = head->flink;
+
+ if (elem != head)
+ __xpt_que_del(head, elem->flink);
+ else
+ elem = 0;
+ return elem;
+}
+
+#define xpt_insque_tail(new, head) __xpt_que_add(new, (head)->blink, head)
+
+static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head)
+{
+ struct xpt_quehead *elem = head->blink;
+
+ if (elem != head)
+ __xpt_que_del(elem->blink, head);
+ else
+ elem = 0;
+ return elem;
+}
+
+/*==========================================================
+**
+** On x86 architecture, write buffers management does
+** not reorder writes to memory. So, using compiler
+** optimization barriers is enough to guarantee some
+** ordering when the CPU is writing data accessed by
+** the NCR.
+** On Alpha architecture, explicit memory barriers have
+** to be used.
+** Other architectures are defaulted to mb() macro if
+** defined, otherwise use compiler barrier.
+**
+**==========================================================
+*/
+
+#if defined(__i386__)
+#define MEMORY_BARRIER() barrier()
+#elif defined(__alpha__)
+#define MEMORY_BARRIER() mb()
+#else
+# ifdef mb
+# define MEMORY_BARRIER() mb()
+# else
+# define MEMORY_BARRIER() barrier()
+# endif
+#endif
+
+/*==========================================================
+**
+** Configuration and Debugging
+**
+**==========================================================
+*/
+
+/*
+** SCSI address of this device.
+** The boot routines should have set it.
+** If not, use this.
+*/
+
+#ifndef SCSI_NCR_MYADDR
+#define SCSI_NCR_MYADDR (7)
+#endif
+
+/*
+** The maximum number of tags per logic unit.
+** Used only for devices that support tags.
+*/
+
+#ifndef SCSI_NCR_MAX_TAGS
+#define SCSI_NCR_MAX_TAGS (8)
+#endif
+
+/*
+** TAGS are actually limited to 64 tags/lun.
+** We need to deal with power of 2, for alignment constraints.


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

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

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part17

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


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

if test "$Scheck" != 17; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

+*/
+#if SCSI_NCR_MAX_TAGS > 64
+#undef SCSI_NCR_MAX_TAGS
+#define SCSI_NCR_MAX_TAGS (64)
+#endif
+
+#define NO_TAG (255)
+
+/*
+** Choose appropriate type for tag bitmap.
+*/
+#if SCSI_NCR_MAX_TAGS > 32
+typedef u_int64 tagmap_t;
+#else
+typedef u_int32 tagmap_t;
+#endif
+
+/*
+** Number of targets supported by the driver.
+** n permits target numbers 0..n-1.
+** Default is 16, meaning targets #0..#15.
+** #7 .. is myself.
+*/
+
+#ifdef SCSI_NCR_MAX_TARGET
+#define MAX_TARGET (SCSI_NCR_MAX_TARGET)
+#else
+#define MAX_TARGET (16)
+#endif
+
+/*
+** Number of logic units supported by the driver.
+** n enables logic unit numbers 0..n-1.
+** The common SCSI devices require only
+** one lun, so take 1 as the default.
+*/
+
+#ifdef SCSI_NCR_MAX_LUN
+#define MAX_LUN SCSI_NCR_MAX_LUN
+#else
+#define MAX_LUN (1)
+#endif
+
+/*
+** Asynchronous pre-scaler (ns). Shall be 40 for
+** the SCSI timings to be compliant.
+*/
+
+#ifndef SCSI_NCR_MIN_ASYNC
+#define SCSI_NCR_MIN_ASYNC (40)
+#endif
+
+/*
+** The maximum number of jobs scheduled for starting.
+** We allocate 4 entries more than the value we announce
+** to the SCSI upper layer. Guess why ! :-)
+*/
+
+#ifdef SCSI_NCR_CAN_QUEUE
+#define MAX_START (SCSI_NCR_CAN_QUEUE + 4)
+#else
+#define MAX_START (MAX_TARGET + 7 * SCSI_NCR_MAX_TAGS)
+#endif
+
+/*
+** The maximum number of segments a transfer is split into.
+** We support up to 127 segments for both read and write.
+** Since we try to avoid phase mismatches by testing the PHASE
+** before each MOV, the both DATA_IN and DATA_OUT scripts do
+** not fit in the 4K on-chip RAM. For this reason, the data
+** scripts are broken into 2 sub-scripts.
+** 80 (MAX_SCATTERL) segments are moved from a sub-script
+** in on-chip RAM. This makes data transfers shorter than
+** 80k (assuming 1k fs) as fast as possible.
+** The 896 allows to handle phase mismatches from SCRIPTS.
+** So, for this chip, we use a simple array of MOV's.
+** Perhaps, using a simple array of MOV's and going with
+** the phase mismatch interrupt is also the best solution
+** for the 895 in Ultra2-mode, since the PHASE test + MOV
+** latency may be enough to fill the SCSI offset for very
+** fast disks like the Cheatah Wide LVD and so, may waste
+** SCSI BUS bandwitch.
+*/
+
+#define MAX_SCATTER (SCSI_NCR_MAX_SCATTER)
+
+#ifdef SCSI_NCR_OPTIMIZE_896
+#define SCR_SG_SIZE (2)
+#define MAX_SCATTERL MAX_SCATTER
+#define MAX_SCATTERH 0
+#else
+#if (MAX_SCATTER > 80)
+#define SCR_SG_SIZE (4)
+#define MAX_SCATTERL 80
+#define MAX_SCATTERH (MAX_SCATTER - MAX_SCATTERL)
+#else
+#define MAX_SCATTERL MAX_SCATTER
+#define MAX_SCATTERH 0
+#endif
+#endif /* SCSI_NCR_OPTIMIZE_896 */
+
+/*
+** Io mapped or memory mapped.
+*/
+
+#if defined(SCSI_NCR_IOMAPPED)
+#define NCR_IOMAPPED
+#endif
+
+/*
+** other
+*/
+
+#define NCR_SNOOP_TIMEOUT (1000000)
+
+/*==========================================================
+**
+** Miscallaneous BSDish defines.
+**
+**==========================================================
+*/
+
+#define u_char unsigned char
+#define u_short unsigned short
+#define u_int unsigned int
+#define u_long unsigned long
+
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif
+
+#ifndef bzero
+#define bzero(d, n) memset((d), 0, (n))
+#endif
+
+#ifndef offsetof
+#define offsetof(t, m) ((size_t) (&((t *)0)->m))
+#endif
+
+/*==========================================================
+**
+** Debugging tags
+**
+**==========================================================
+*/
+
+#define DEBUG_ALLOC (0x0001)
+#define DEBUG_PHASE (0x0002)
+#define DEBUG_POLL (0x0004)
+#define DEBUG_QUEUE (0x0008)
+#define DEBUG_RESULT (0x0010)
+#define DEBUG_SCATTER (0x0020)
+#define DEBUG_SCRIPT (0x0040)
+#define DEBUG_TINY (0x0080)
+#define DEBUG_TIMING (0x0100)
+#define DEBUG_NEGO (0x0200)
+#define DEBUG_TAGS (0x0400)
+#define DEBUG_FREEZE (0x0800)
+#define DEBUG_RESTART (0x1000)
+
+/*
+** Enable/Disable debug messages.
+** Can be changed at runtime too.
+*/
+
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
+ #define DEBUG_FLAGS ncr_debug
+#else
+ #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS
+#endif
+
+/*
+** SMP threading.
+**
+** Assuming that SMP systems are generally high end systems and may
+** use several SCSI adapters, we are using one lock per controller
+** instead of some global one. For the moment (linux-2.1.95), driver's
+** entry points are called with the 'io_request_lock' lock held, so:
+** - We are uselessly loosing a couple of micro-seconds to lock the
+** controller data structure.
+** - But the driver is not broken by design for SMP and so can be
+** more resistant to bugs or bad changes in the IO sub-system code.
+** - A small advantage could be that the interrupt code is grained as
+** wished (e.g.: threaded by controller).
+*/
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+
+spinlock_t sym53c8xx_lock;
+#define NCR_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags)
+#define NCR_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags)
+
+#define NCR_INIT_LOCK_NCB(np) spin_lock_init(&np->smp_lock);
+#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags)
+#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags)
+
+# if LINUX_VERSION_CODE < LinuxVersionCode(2,3,99)
+
+# define NCR_LOCK_SCSI_DONE(np, flags) \
+ spin_lock_irqsave(&io_request_lock, flags)
+# define NCR_UNLOCK_SCSI_DONE(np, flags) \
+ spin_unlock_irqrestore(&io_request_lock, flags)
+
+# else
+
+# define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
+# define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
+
+# endif
+
+#else
+
+#define NCR_LOCK_DRIVER(flags) do { save_flags(flags); cli(); } while (0)
+#define NCR_UNLOCK_DRIVER(flags) do { restore_flags(flags); } while (0)
+
+#define NCR_INIT_LOCK_NCB(np) do { } while (0)
+#define NCR_LOCK_NCB(np, flags) do { save_flags(flags); cli(); } while (0)
+#define NCR_UNLOCK_NCB(np, flags) do { restore_flags(flags); } while (0)
+
+#define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
+#define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
+
+#endif
+
+/*
+** Address translation
+**
+** The driver has to provide bus memory addresses to
+** the script processor. Because some architectures use
+** different physical addressing scheme from the PCI BUS,
+** we use virt_to_bus() instead of virt_to_phys().
+*/
+
+#define vtobus(p) virt_to_bus(p)
+
+/*


+** Memory mapped IO
+**

+** Since linux-2.1, we must use ioremap() to map the io memory space.
+** iounmap() to unmap it. That allows portability.
+** Linux 1.3.X and 2.0.X allow to remap physical pages addresses greater
+** than the highest physical memory address to kernel virtual pages with
+** vremap() / vfree(). That was not portable but worked with i386
+** architecture.
+*/
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
+#define ioremap vremap
+#define iounmap vfree
+#endif
+
+#ifdef __sparc__
+#define remap_pci_mem(base, size) ((u_long) __va(base))
+#define unmap_pci_mem(vaddr, size)
+#define pcivtobus(p) ((p) & pci_dvma_mask)
+#else /* __sparc__ */
+#define pcivtobus(p) (p)
+
+#if !defined(NCR_IOMAPPED) || defined(__i386__)
+__initfunc(
+static u_long remap_pci_mem(u_long base, u_long size)
+)
+{
+ u_long page_base = ((u_long) base) & PAGE_MASK;
+ u_long page_offs = ((u_long) base) - page_base;
+ u_long page_remapped = (u_long) ioremap(page_base, page_offs+size);
+
+ return page_remapped? (page_remapped + page_offs) : 0UL;
+}
+
+__initfunc(
+static void unmap_pci_mem(u_long vaddr, u_long size)
+)
+{
+ if (vaddr)
+ iounmap((void *) (vaddr & PAGE_MASK));
+}
+#endif /* !NCR_IOMAPPED || __i386__ */
+#endif /* __sparc__ */
+
+/*
+** Insert a delay in micro-seconds and milli-seconds.
+** -------------------------------------------------
+** Under Linux, udelay() is restricted to delay < 1 milli-second.
+** In fact, it generally works for up to 1 second delay.
+** Since 2.1.105, the mdelay() function is provided for delays
+** in milli-seconds.
+** Under 2.0 kernels, udelay() is an inline function that is very
+** inaccurate on Pentium processors.
+*/
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,105)
+#define UDELAY udelay
+#define MDELAY mdelay
+#else
+static void UDELAY(long us) { udelay(us); }
+static void MDELAY(long ms) { while (ms--) UDELAY(1000); }
+#endif
+
+/*
+** Simple power of two buddy-like allocator
+** ----------------------------------------
+** This simple code is not intended to be fast, but to provide
+** power of 2 aligned memory allocations.
+** Since the SCRIPTS processor only supplies 8 bit arithmetic,
+** this allocator allows simple and fast address calculations
+** from the SCRIPTS code. In addition, cache line alignment
+** is guaranteed for power of 2 cache line size.
+*/
+
+#define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */
+#define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum (for now (ever?) */
+typedef unsigned long addr; /* Enough bits to bit-hack addresses */
+
+#define MEMO_FREE_UNUSED /* Free unused pages immediately */
+
+struct m_link {
+ struct m_link *next; /* Simple links are enough */
+};
+
+#ifndef GFP_DMA_32BIT
+#define GFP_DMA_32BIT 0 /* Will this flag ever exist */
+#endif
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
+#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order)
+#else
+#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order, 0)
+#endif
+
+/*
+** Lists of available memory chunks.
+** Starts with 16 bytes chunks until 1 PAGE chunks.
+*/
+static struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
+
+/*
+** Allocate a memory area aligned on the lowest power of 2
+** greater than the requested size.
+*/
+static void *__m_alloc(int size)
+{
+ int i = 0;
+ int s = (1 << MEMO_SHIFT);
+ int j;
+ addr a ;
+
+ if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+ return 0;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ j = i;
+ while (!h[j].next) {
+ if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+ h[j].next = (struct m_link *)get_pages(MEMO_PAGE_ORDER);
+ if (h[j].next)
+ h[j].next->next = 0;
+ break;
+ }
+ ++j;
+ s <<= 1;
+ }
+ a = (addr) h[j].next;
+ if (a) {
+ h[j].next = h[j].next->next;
+ while (j > i) {
+ j -= 1;
+ s >>= 1;
+ h[j].next = (struct m_link *) (a+s);
+ h[j].next->next = 0;
+ }
+ }
+#ifdef DEBUG
+ printk("m_alloc(%d) = %p\n", size, (void *) a);
+#endif
+ return (void *) a;
+}
+
+/*
+** Free a memory area allocated using m_alloc().
+** Coalesce buddies.
+** Free pages that become unused if MEMO_FREE_UNUSED is defined.
+*/
+static void __m_free(void *ptr, int size)
+{
+ int i = 0;
+ int s = (1 << MEMO_SHIFT);
+ struct m_link *q;
+ addr a, b;
+
+#ifdef DEBUG
+ printk("m_free(%p, %d)\n", ptr, size);
+#endif
+
+ if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+ return;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ a = (addr) ptr;
+
+ while (1) {
+#ifdef MEMO_FREE_UNUSED
+ if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+ free_pages(a, MEMO_PAGE_ORDER);
+ break;
+ }
+#endif
+ b = a ^ s;
+ q = &h[i];
+ while (q->next && q->next != (struct m_link *) b) {
+ q = q->next;
+ }
+ if (!q->next) {
+ ((struct m_link *) a)->next = h[i].next;
+ h[i].next = (struct m_link *) a;
+ break;
+ }
+ q->next = q->next->next;
+ a = a & b;
+ s <<= 1;
+ ++i;
+ }
+}
+
+#define MEMO_WARN 1
+
+/*
+** The memory pool is shared by all instances.
+** We use a global SMP LOCK to be SMP safe.
+*/
+
+static void *m_calloc(int size, char *name, int uflags)
+{
+ u_long flags;
+ void *p;
+
+ NCR_LOCK_DRIVER(flags);
+ p = __m_alloc(size);
+ NCR_UNLOCK_DRIVER(flags);
+
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printk ("new %s[%d] @%p.\n", name, size, p);
+
+ if (p)
+ memset(p, 0, size);
+ else if (uflags & MEMO_WARN)
+ printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
+
+ return p;
+}
+
+static void m_free(void *ptr, int size, char *name)
+{
+ u_long flags;
+
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printk ("freeing %s[%d] @%p.\n", name, size, ptr);
+
+ NCR_LOCK_DRIVER(flags);
+ __m_free(ptr, size);
+ NCR_UNLOCK_DRIVER(flags);
+}
+
+/*
+** Transfer direction
+**
+** Low-level scsi drivers under Linux do not receive the expected
+** data transfer direction from upper scsi drivers.
+** The driver will only check actual data direction for common
+** scsi opcodes. Other ones may cause problem, since they may
+** depend on device type or be vendor specific.
+** I would prefer to never trust the device for data direction,
+** but that is not possible.
+**
+** The original driver requires the expected direction to be known.
+** The Linux version of the driver has been enhanced in order to
+** be able to transfer data in the direction choosen by the target.
+*/
+
+#define XFER_IN (1)
+#define XFER_OUT (2)
+
+/*
+** Head of list of NCR boards
+**
+** For kernel version < 1.3.70, host is retrieved by its irq level.
+** For later kernels, the internal host control block address
+** (struct ncb) is used as device id parameter of the irq stuff.
+*/
+
+static struct Scsi_Host *first_host = NULL;
+
+
+/*
+** /proc directory entry and proc_info function
+*/
+
+static struct proc_dir_entry proc_scsi_sym53c8xx = {
+ PROC_SCSI_SYM53C8XX, 9, NAME53C8XX,


+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};

+#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
+ int length, int hostno, int func);
+#endif
+
+/*
+** Driver setup.
+**
+** This structure is initialized from linux config options.
+** It can be overridden at boot-up by the boot command line.
+*/
+#define SCSI_NCR_MAX_EXCLUDES 8
+struct ncr_driver_setup {
+ u_char master_parity;
+ u_char scsi_parity;
+ u_char disconnection;
+ u_char special_features;
+ u_char ultra_scsi;
+ u_char force_sync_nego;
+ u_char reverse_probe;
+ u_char pci_fix_up;
+ u_char use_nvram;
+ u_char verbose;
+ u_char default_tags;
+ u_short default_sync;
+ u_short debug;
+ u_char burst_max;
+ u_char led_pin;
+ u_char max_wide;
+ u_char settle_delay;
+ u_char diff_support;
+ u_char irqm;
+ u_char bus_check;


+ u_char optimize;
+ u_char recovery;
+ u_int excludes[SCSI_NCR_MAX_EXCLUDES];

+ char tag_ctrl[100];
+};
+
+static struct ncr_driver_setup
+ driver_setup = SCSI_NCR_DRIVER_SETUP;
+
+#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+static struct ncr_driver_setup
+ driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
+# ifdef MODULE
+char *sym53c8xx = 0; /* command line passed by insmod */
+# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+MODULE_PARM(sym53c8xx, "s");
+# endif
+# endif
+#endif
+
+/*
+** Other Linux definitions
+*/
+#define SetScsiResult(cmd, h_sts, s_sts) \
+ cmd->result = (((h_sts) << 16) + ((s_sts) & 0x7f))
+
+static void sym53c8xx_select_queue_depths(
+ struct Scsi_Host *host, struct scsi_device *devlist);
+static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
+static void sym53c8xx_timeout(unsigned long np);
+
+#define initverbose (driver_setup.verbose)
+#define bootverbose (np->verbose)
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+/*
+** Symbios NvRAM data format
+*/
+#define SYMBIOS_NVRAM_SIZE 368
+#define SYMBIOS_NVRAM_ADDRESS 0x100
+
+struct Symbios_nvram {
+/* Header 6 bytes */
+ u_short type; /* 0x0000 */
+ u_short byte_count; /* excluding header/trailer */
+ u_short checksum;
+
+/* Controller set up 20 bytes */
+ u_char v_major; /* 0x00 */
+ u_char v_minor; /* 0x30 */
+ u_int32 boot_crc;
+ u_short flags;
+#define SYMBIOS_SCAM_ENABLE (1)
+#define SYMBIOS_PARITY_ENABLE (1<<1)
+#define SYMBIOS_VERBOSE_MSGS (1<<2)
+#define SYMBIOS_CHS_MAPPING (1<<3)
+#define SYMBIOS_NO_NVRAM (1<<3) /* ??? */
+ u_short flags1;
+#define SYMBIOS_SCAN_HI_LO (1)
+ u_short term_state;
+#define SYMBIOS_TERM_CANT_PROGRAM (0)
+#define SYMBIOS_TERM_ENABLED (1)
+#define SYMBIOS_TERM_DISABLED (2)
+ u_short rmvbl_flags;
+#define SYMBIOS_RMVBL_NO_SUPPORT (0)
+#define SYMBIOS_RMVBL_BOOT_DEVICE (1)
+#define SYMBIOS_RMVBL_MEDIA_INSTALLED (2)
+ u_char host_id;
+ u_char num_hba; /* 0x04 */
+ u_char num_devices; /* 0x10 */
+ u_char max_scam_devices; /* 0x04 */
+ u_char num_valid_scam_devives; /* 0x00 */
+ u_char rsvd;
+
+/* Boot order 14 bytes * 4 */
+ struct Symbios_host{
+ u_short type; /* 4:8xx / 0:nok */
+ u_short device_id; /* PCI device id */
+ u_short vendor_id; /* PCI vendor id */
+ u_char bus_nr; /* PCI bus number */
+ u_char device_fn; /* PCI device/function number << 3*/
+ u_short word8;
+ u_short flags;
+#define SYMBIOS_INIT_SCAN_AT_BOOT (1)
+ u_short io_port; /* PCI io_port address */
+ } host[4];
+
+/* Targets 8 bytes * 16 */
+ struct Symbios_target {
+ u_char flags;
+#define SYMBIOS_DISCONNECT_ENABLE (1)
+#define SYMBIOS_SCAN_AT_BOOT_TIME (1<<1)
+#define SYMBIOS_SCAN_LUNS (1<<2)
+#define SYMBIOS_QUEUE_TAGS_ENABLED (1<<3)
+ u_char rsvd;
+ u_char bus_width; /* 0x08/0x10 */
+ u_char sync_offset;
+ u_short sync_period; /* 4*period factor */
+ u_short timeout;
+ } target[16];
+/* Scam table 8 bytes * 4 */
+ struct Symbios_scam {
+ u_short id;
+ u_short method;
+#define SYMBIOS_SCAM_DEFAULT_METHOD (0)
+#define SYMBIOS_SCAM_DONT_ASSIGN (1)
+#define SYMBIOS_SCAM_SET_SPECIFIC_ID (2)
+#define SYMBIOS_SCAM_USE_ORDER_GIVEN (3)
+ u_short status;
+#define SYMBIOS_SCAM_UNKNOWN (0)
+#define SYMBIOS_SCAM_DEVICE_NOT_FOUND (1)
+#define SYMBIOS_SCAM_ID_NOT_SET (2)
+#define SYMBIOS_SCAM_ID_VALID (3)
+ u_char target_id;
+ u_char rsvd;
+ } scam[4];
+
+ u_char spare_devices[15*8];
+ u_char trailer[6]; /* 0xfe 0xfe 0x00 0x00 0x00 0x00 */
+};
+typedef struct Symbios_nvram Symbios_nvram;
+typedef struct Symbios_host Symbios_host;
+typedef struct Symbios_target Symbios_target;
+typedef struct Symbios_scam Symbios_scam;
+
+/*
+** Tekram NvRAM data format.
+*/
+#define TEKRAM_NVRAM_SIZE 64
+#define TEKRAM_NVRAM_ADDRESS 0
+
+struct Tekram_nvram {
+ struct Tekram_target {
+ u_char flags;
+#define TEKRAM_PARITY_CHECK (1)
+#define TEKRAM_SYNC_NEGO (1<<1)
+#define TEKRAM_DISCONNECT_ENABLE (1<<2)
+#define TEKRAM_START_CMD (1<<3)
+#define TEKRAM_TAGGED_COMMANDS (1<<4)
+#define TEKRAM_WIDE_NEGO (1<<5)
+ u_char sync_index;
+ u_short word2;
+ } target[16];
+ u_char host_id;
+ u_char flags;
+#define TEKRAM_MORE_THAN_2_DRIVES (1)
+#define TEKRAM_DRIVES_SUP_1GB (1<<1)
+#define TEKRAM_RESET_ON_POWER_ON (1<<2)
+#define TEKRAM_ACTIVE_NEGATION (1<<3)
+#define TEKRAM_IMMEDIATE_SEEK (1<<4)
+#define TEKRAM_SCAN_LUNS (1<<5)
+#define TEKRAM_REMOVABLE_FLAGS (3<<6) /* 0: disable; 1: boot device; 2:all */
+ u_char boot_delay_index;
+ u_char max_tags_index;
+ u_short flags1;
+#define TEKRAM_F2_F6_ENABLED (1)
+ u_short spare[29];
+};
+typedef struct Tekram_nvram Tekram_nvram;
+typedef struct Tekram_target Tekram_target;
+
+static u_char Tekram_sync[12] __initdata = {25,31,37,43,50,62,75,125,12,15,18,21};
+
+#endif /* SCSI_NCR_NVRAM_SUPPORT */
+
+/*
+** Structures used by sym53c8xx_detect/sym53c8xx_pci_init to
+** transmit device configuration to the ncr_attach() function.
+*/
+typedef struct {
+ int bus;
+ u_char device_fn;
+ u_long base;
+ u_long base_2;
+ u_long io_port;
+ int irq;
+/* port and reg fields to use INB, OUTB macros */
+ u_long base_io;
+ volatile struct ncr_reg *reg;
+} ncr_slot;
+
+typedef struct {
+ int type;
+#define SCSI_NCR_SYMBIOS_NVRAM (1)
+#define SCSI_NCR_TEKRAM_NVRAM (2)
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ union {
+ Symbios_nvram Symbios;
+ Tekram_nvram Tekram;
+ } data;
+#endif
+} ncr_nvram;
+
+/*
+** Structure used by sym53c8xx_detect/sym53c8xx_pci_init
+** to save data on each detected board for ncr_attach().
+*/
+typedef struct {
+ ncr_slot slot;
+ ncr_chip chip;
+ ncr_nvram *nvram;
+ u_char host_id;
+#ifdef SCSI_NCR_PQS_PDS_SUPPORT
+ u_char pqs_pds;
+#endif
+ int attach_done;
+} ncr_device;
+
+/*==========================================================
+**
+** assert ()
+**
+**==========================================================
+**
+** modified copy from 386bsd:/usr/include/sys/assert.h
+**
+**----------------------------------------------------------
+*/
+
+#define assert(expression) { \
+ if (!(expression)) { \
+ (void)panic( \
+ "assertion \"%s\" failed: file \"%s\", line %d\n", \
+ #expression, \
+ __FILE__, __LINE__); \
+ } \
+}
+
+/*==========================================================
+**
+** Big/Little endian support.


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

+** If the NCR uses big endian addressing mode over the
+** PCI, actual io register addresses for byte and word
+** accesses must be changed according to lane routing.
+** Btw, ncr_offb() and ncr_offw() macros only apply to
+** constants and so donnot generate bloated code.
+*/
+
+#if defined(SCSI_NCR_BIG_ENDIAN)
+
+#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))
+#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))
+
+#else
+
+#define ncr_offb(o) (o)
+#define ncr_offw(o) (o)
+
+#endif
+
+/*
+** If the CPU and the NCR use same endian-ness adressing,
+** no byte reordering is needed for script patching.
+** Macro cpu_to_scr() is to be used for script patching.
+** Macro scr_to_cpu() is to be used for getting a DWORD
+** from the script.
+*/
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_le32(dw)
+#define scr_to_cpu(dw) le32_to_cpu(dw)
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_be32(dw)
+#define scr_to_cpu(dw) be32_to_cpu(dw)
+
+#else
+
+#define cpu_to_scr(dw) (dw)
+#define scr_to_cpu(dw) (dw)
+
+#endif
+
+/*==========================================================
+**
+** Access to the controller chip.
+**
+** If NCR_IOMAPPED is defined, the driver will use
+** normal IOs instead of the MEMORY MAPPED IO method
+** recommended by PCI specifications.
+** If all PCI bridges, host brigdes and architectures
+** would have been correctly designed for PCI, this
+** option would be useless.


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

+** If the CPU and the NCR use same endian-ness adressing,
+** no byte reordering is needed for accessing chip io
+** registers. Functions suffixed by '_raw' are assumed
+** to access the chip over the PCI without doing byte
+** reordering. Functions suffixed by '_l2b' are
+** assumed to perform little-endian to big-endian byte
+** reordering, those suffixed by '_b2l' blah, blah,
+** blah, ...
+*/
+
+#if defined(NCR_IOMAPPED)
+
+/*
+** IO mapped only input / ouput
+*/
+
+#define INB_OFF(o) inb (np->base_io + ncr_offb(o))
+#define OUTB_OFF(o, val) outb ((val), np->base_io + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_l2b (np->base_io + ncr_offw(o))
+#define INL_OFF(o) inl_l2b (np->base_io + (o))
+
+#define OUTW_OFF(o, val) outw_b2l ((val), np->base_io + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_b2l ((val), np->base_io + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_b2l (np->base_io + ncr_offw(o))
+#define INL_OFF(o) inl_b2l (np->base_io + (o))
+
+#define OUTW_OFF(o, val) outw_l2b ((val), np->base_io + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_l2b ((val), np->base_io + (o))
+
+#else
+
+#define INW_OFF(o) inw_raw (np->base_io + ncr_offw(o))
+#define INL_OFF(o) inl_raw (np->base_io + (o))
+
+#define OUTW_OFF(o, val) outw_raw ((val), np->base_io + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_raw ((val), np->base_io + (o))
+
+#endif /* ENDIANs */
+
+#else /* defined NCR_IOMAPPED */
+
+/*
+** MEMORY mapped IO input / output
+*/
+
+#define INB_OFF(o) readb((char *)np->reg + ncr_offb(o))
+#define OUTB_OFF(o, val) writeb((val), (char *)np->reg + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_l2b((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_b2l((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o))
+
+#else
+
+#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_raw((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o))
+
+#endif
+
+#endif /* defined NCR_IOMAPPED */
+
+#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))
+#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))
+#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))
+
+#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))
+
+/*
+** Set bit field ON, OFF
+*/
+
+#define OUTONB(r, m) OUTB(r, INB(r) | (m))
+#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
+#define OUTONW(r, m) OUTW(r, INW(r) | (m))
+#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
+#define OUTONL(r, m) OUTL(r, INL(r) | (m))
+#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
+
+
+/*==========================================================
+**
+** Command control block states.
+**
+**==========================================================
+*/
+
+#define HS_IDLE (0)
+#define HS_BUSY (1)
+#define HS_NEGOTIATE (2) /* sync/wide data transfer*/
+#define HS_DISCONNECT (3) /* Disconnected by target */
+
+#define HS_DONEMASK (0x80)
+#define HS_COMPLETE (4|HS_DONEMASK)
+#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */
+#define HS_RESET (6|HS_DONEMASK) /* SCSI reset */
+#define HS_ABORTED (7|HS_DONEMASK) /* Transfer aborted */
+#define HS_TIMEOUT (8|HS_DONEMASK) /* Software timeout */
+#define HS_FAIL (9|HS_DONEMASK) /* SCSI or PCI bus errors */
+#define HS_UNEXPECTED (10|HS_DONEMASK)/* Unexpected disconnect */
+
+#define DSA_INVALID 0xffffffff
+
+/*==========================================================
+**
+** Software Interrupt Codes
+**
+**==========================================================
+*/
+
+#define SIR_BAD_STATUS (1)
+#define SIR_SEL_ATN_NO_MSG_OUT (2)
+#define SIR_NEGO_SYNC (3)
+#define SIR_NEGO_WIDE (4)
+#define SIR_NEGO_FAILED (5)
+#define SIR_NEGO_PROTO (6)
+#define SIR_REJECT_RECEIVED (7)
+#define SIR_REJECT_TO_SEND (8)
+#define SIR_IGN_RESIDUE (9)
+#define SIR_MISSING_SAVE (10)
+#define SIR_RESEL_NO_MSG_IN (11)
+#define SIR_RESEL_NO_IDENTIFY (12)
+#define SIR_RESEL_BAD_LUN (13)
+#define SIR_UNUSED_14 (14)
+#define SIR_RESEL_BAD_I_T_L (15)
+#define SIR_RESEL_BAD_I_T_L_Q (16)
+#define SIR_UNUSED_17 (17)
+#define SIR_RESEL_ABORTED (18)
+#define SIR_MSG_OUT_DONE (19)
+#define SIR_MAX (19)
+
+/*==========================================================
+**
+** Extended error codes.
+** xerr_status field of struct ccb.
+**
+**==========================================================
+*/
+
+#define XE_OK (0)
+#define XE_EXTRA_DATA (1) /* unexpected data phase */
+#define XE_BAD_PHASE (2) /* illegal phase (4/5) */
+
+/*==========================================================
+**
+** Negotiation status.
+** nego_status field of struct ccb.
+**
+**==========================================================
+*/
+
+#define NS_SYNC (1)
+#define NS_WIDE (2)
+
+/*==========================================================
+**
+** "Special features" of targets.
+** quirks field of struct tcb.
+** actualquirks field of struct ccb.
+**
+**==========================================================
+*/
+
+#define QUIRK_AUTOSAVE (0x01)
+#define QUIRK_NOMSG (0x02)
+#define QUIRK_NOSYNC (0x10)
+#define QUIRK_NOWIDE16 (0x20)
+
+/*==========================================================
+**
+** Capability bits in Inquire response byte 7.
+**
+**==========================================================
+*/
+
+#define INQ7_QUEUE (0x02)
+#define INQ7_SYNC (0x10)
+#define INQ7_WIDE16 (0x20)
+
+/*==========================================================
+**
+** A CCB hashed table is used to retrieve CCB address
+** from DSA value.
+**
+**==========================================================
+*/
+
+#define CCB_HASH_SHIFT 8
+#define CCB_HASH_SIZE (1UL << CCB_HASH_SHIFT)
+#define CCB_HASH_MASK (CCB_HASH_SIZE-1)
+#define CCB_HASH_CODE(dsa) (((dsa) >> 11) & CCB_HASH_MASK)
+
+/*==========================================================
+**
+** Declaration of structs.
+**
+**==========================================================
+*/
+
+struct tcb;
+struct lcb;
+struct ccb;
+struct ncb;
+struct script;
+
+typedef struct ncb * ncb_p;
+typedef struct tcb * tcb_p;
+typedef struct lcb * lcb_p;
+typedef struct ccb * ccb_p;
+
+struct link {
+ ncrcmd l_cmd;
+ ncrcmd l_paddr;
+};
+
+struct usrcmd {
+ u_long target;
+ u_long lun;
+ u_long data;
+ u_long cmd;
+};
+
+#define UC_SETSYNC 10
+#define UC_SETTAGS 11
+#define UC_SETDEBUG 12
+#define UC_SETORDER 13
+#define UC_SETWIDE 14
+#define UC_SETFLAG 15
+#define UC_CLEARPROF 16
+#define UC_SETVERBOSE 17
+
+#define UF_TRACE (0x01)
+#define UF_NODISC (0x02)
+#define UF_NOSCAN (0x04)
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+/*
+** profiling data (per host)
+*/
+
+struct profile {
+ u_long num_trans;
+ u_long num_disc;
+ u_long num_disc0;
+ u_long num_break;
+ u_long num_int;
+ u_long num_fly;
+ u_long num_kbytes;
+#if 000
+ u_long num_br1k;
+ u_long num_br2k;
+ u_long num_br4k;
+ u_long num_br8k;
+ u_long num_brnk;
+#endif
+};
+#endif
+
+/*========================================================================
+**
+** Declaration of structs: target control block
+**
+**========================================================================
+*/
+struct tcb {
+ /*----------------------------------------------------------------
+ ** LUN tables.
+ ** An array of bus addresses is used on reselection by
+ ** the SCRIPT.
+ **----------------------------------------------------------------
+ */
+ u_int32 *luntbl; /* lcbs bus address table */
+ u_int32 b_luntbl; /* bus address of this table */
+ lcb_p lp[MAX_LUN]; /* The lcb's of this tcb */
+
+ /*----------------------------------------------------------------
+ ** Target capabilities.
+ **----------------------------------------------------------------
+ */
+ u_char inq_done; /* Target capabilities received */
+ u_char inq_byte7; /* Contains these capabilities */
+
+ /*----------------------------------------------------------------
+ ** Pointer to the ccb used for negotiation.
+ ** Prevent from starting a negotiation for all queued commands
+ ** when tagged command queuing is enabled.
+ **----------------------------------------------------------------
+ */
+ ccb_p nego_cp;
+
+ /*----------------------------------------------------------------
+ ** statistical data
+ **----------------------------------------------------------------
+ */
+ u_long transfers;
+ u_long bytes;
+
+ /*----------------------------------------------------------------
+ ** negotiation of wide and synch transfer and device quirks.
+ ** sval and wval are read from SCRIPTS and so have alignment
+ ** constraints.
+ **----------------------------------------------------------------
+ */
+/*0*/ u_char minsync;
+/*1*/ u_char sval;
+/*2*/ u_short period;
+/*0*/ u_char maxoffs;
+/*1*/ u_char quirks;
+/*2*/ u_char widedone;
+/*3*/ u_char wval;
+
+ /*----------------------------------------------------------------
+ ** User settable limits and options.
+ ** These limits are read from the NVRAM if present.
+ **----------------------------------------------------------------
+ */
+ u_char usrsync;
+ u_char usrwide;
+ u_char usrtags;
+ u_char usrflag;
+};
+
+/*========================================================================
+**
+** Declaration of structs: lun control block
+**
+**========================================================================
+*/
+struct lcb {
+ /*----------------------------------------------------------------
+ ** On reselection, SCRIPTS use this value as a JUMP address
+ ** after the IDENTIFY has been successfully received.
+ ** This field is set to 'resel_tag' if TCQ is enabled and
+ ** to 'resel_notag' if TCQ is disabled.
+ ** (Must be at zero due to bad lun handling on reselection)
+ **----------------------------------------------------------------
+ */
+/*0*/ u_int32 resel_task;
+
+ /*----------------------------------------------------------------
+ ** Task table used by the script processor to retrieve the
+ ** task corresponding to a reselected nexus. The TAG is used
+ ** as offset to determine the corresponding entry.
+ ** Each entry contains the associated CCB bus address.
+ **----------------------------------------------------------------
+ */
+ u_int32 tasktbl_0; /* Used if TCQ not enabled */
+ u_int32 *tasktbl;
+ u_int32 b_tasktbl;
+
+ /*----------------------------------------------------------------
+ ** CCB queue management.
+ **----------------------------------------------------------------
+ */
+ XPT_QUEHEAD busy_ccbq; /* Queue of busy CCBs */
+ XPT_QUEHEAD wait_ccbq; /* Queue of waiting for IO CCBs */
+ u_char busyccbs; /* CCBs busy for this lun */
+ u_char queuedccbs; /* CCBs queued to the controller*/
+ u_char queuedepth; /* Queue depth for this lun */
+ u_char scdev_depth; /* SCSI device queue depth */
+ u_char maxnxs; /* Max possible nexuses */
+
+ /*----------------------------------------------------------------
+ ** Control of tagged command queuing.
+ ** Tags allocation is performed using a circular buffer.
+ ** This avoids using a loop for tag allocation.
+ **----------------------------------------------------------------
+ */
+ u_char ia_tag; /* Tag allocation index */
+ u_char if_tag; /* Tag release index */
+ u_char cb_tags[SCSI_NCR_MAX_TAGS]; /* Circular tags buffer */
+ u_char usetags; /* Command queuing is active */
+ u_char maxtags; /* Max NR of tags asked by user */
+ u_char numtags; /* Current number of tags */
+ u_char inq_byte7; /* Store unit CmdQ capabitility */
+
+ /*----------------------------------------------------------------
+ ** QUEUE FULL and ORDERED tag control.
+ **----------------------------------------------------------------
+ */
+ u_short num_good; /* Nr of GOOD since QUEUE FULL */
+ tagmap_t tags_umap; /* Used tags bitmap */
+ tagmap_t tags_smap; /* Tags in use at 'tag_stime' */
+ u_long tags_stime; /* Last time we set smap=umap */
+};
+
+/*========================================================================
+**
+** Declaration of structs: actions for a task.
+**
+**========================================================================
+**
+** It is part of the CCB and is called by the scripts processor to
+** start or restart the data structure (nexus).
+**
+**------------------------------------------------------------------------
+*/
+struct action {
+ u_int32 start;
+ u_int32 restart;
+};
+
+/*========================================================================
+**
+** Declaration of structs: Phase mismatch context.
+**
+**========================================================================
+**
+** It is part of the CCB and is used as parameters for the DATA
+** pointer. We need two contexts to handle correctly the SAVED
+** DATA POINTER.
+**
+**------------------------------------------------------------------------
+*/
+struct pm_ctx {
+ struct scr_tblmove sg; /* Updated interrupted SG block */
+ u_int32 ret; /* SCRIPT return address */
+};
+
+/*========================================================================
+**
+** Declaration of structs: global HEADER.
+**
+**========================================================================
+**
+** In earlier driver versions, this substructure was copied from the
+** ccb to a global address after selection (or reselection) and copied
+** back before disconnect. Since we are now using LOAD/STORE DSA
+** RELATIVE instructions, the script is able to access directly these
+** fields, and so, this header is no more copied.
+**
+**------------------------------------------------------------------------
+*/
+
+struct head {
+ /*----------------------------------------------------------------
+ ** Start and restart SCRIPTS addresses (must be at 0).
+ **----------------------------------------------------------------
+ */
+ struct action go;
+
+ /*----------------------------------------------------------------
+ ** Saved data pointer.
+ ** Points to the position in the script responsible for the
+ ** actual transfer of data.
+ ** It's written after reception of a SAVE_DATA_POINTER message.
+ ** The goalpointer points after the last transfer command.
+ **----------------------------------------------------------------
+ */
+ u_int32 savep;
+ u_int32 lastp;
+ u_int32 goalp;
+
+ /*----------------------------------------------------------------
+ ** Alternate data pointer.
+ ** They are copied back to savep/lastp/goalp by the SCRIPTS
+ ** when the direction is unknown and the device claims data out.
+ **----------------------------------------------------------------
+ */
+ u_int32 wlastp;
+ u_int32 wgoalp;
+
+ /*----------------------------------------------------------------
+ ** Status fields.
+ **----------------------------------------------------------------
+ */
+ u_char scr_st[4]; /* script status */
+ u_char status[4]; /* host status */
+};
+
+/*
+** The status bytes are used by the host and the script processor.
+**
+** The last four bytes (status[4]) are copied to the scratchb register
+** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect,
+** and copied back just after disconnecting.
+** Inside the script the XX_REG are used.
+**
+** The first four bytes (scr_st[4]) are used inside the script by
+** "LOAD/STORE" commands.
+** Because source and destination must have the same alignment
+** in a DWORD, the fields HAVE to be at the choosen offsets.
+** xerr_st 0 (0x34) scratcha
+** sync_st 1 (0x05) sxfer
+** wide_st 3 (0x03) scntl3
+*/
+
+/*
+** Last four bytes (script)
+*/
+#define QU_REG scr0
+#define HS_REG scr1
+#define HS_PRT nc_scr1
+#define SS_REG scr2
+#define SS_PRT nc_scr2
+#define HF_REG scr3
+#define HF_PRT nc_scr3
+
+/*
+** Last four bytes (host)
+*/
+#define actualquirks phys.header.status[0]
+#define host_status phys.header.status[1]
+#define scsi_status phys.header.status[2]
+#define host_flags phys.header.status[3]
+
+/*
+** Host flags
+*/
+#define HF_IN_PM0 1u
+#define HF_IN_PM1 (1u<<1)
+#define HF_ACT_PM (1u<<2)
+#define HF_DP_SAVED (1u<<3)
+#define HF_PAR_ERR (1u<<4)
+#define HF_DATA_ST (1u<<5)
+#define HF_PM_TO_C (1u<<6)
+
+/*
+** First four bytes (script)
+*/
+#define xerr_st header.scr_st[0]
+#define sync_st header.scr_st[1]
+#define nego_st header.scr_st[2]
+#define wide_st header.scr_st[3]
+
+/*
+** First four bytes (host)
+*/
+#define xerr_status phys.xerr_st
+#define nego_status phys.nego_st
+
+/*==========================================================
+**
+** Declaration of structs: Data structure block
+**
+**==========================================================
+**
+** During execution of a ccb by the script processor,
+** the DSA (data structure address) register points
+** to this substructure of the ccb.
+** This substructure contains the header with
+** the script-processor-changable data and
+** data blocks for the indirect move commands.
+**
+**----------------------------------------------------------
+*/
+
+struct dsb {
+
+ /*
+ ** Header.
+ */
+
+ struct head header;
+
+ /*
+ ** Table data for Script
+ */
+
+ struct scr_tblsel select;
+ struct scr_tblmove smsg ;
+ struct scr_tblmove cmd ;
+ struct scr_tblmove sense ;
+ struct scr_tblmove data [MAX_SCATTER];
+
+ /*
+ ** Phase mismatch contexts.
+ ** We need two to handle correctly the
+ ** SAVED DATA POINTER.
+ */
+
+ struct pm_ctx pm0;
+ struct pm_ctx pm1;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ /*
+ ** Disconnection counter
+ */
+ u_int32 num_disc;
+#endif
+};
+
+
+/*========================================================================
+**
+** Declaration of structs: Command control block.
+**
+**========================================================================
+*/
+struct ccb {
+ /*----------------------------------------------------------------
+ ** This is the data structure which is pointed by the DSA
+ ** register when it is executed by the script processor.
+ ** It must be the first entry.
+ **----------------------------------------------------------------
+ */
+ struct dsb phys;
+
+ /*----------------------------------------------------------------
+ ** The general SCSI driver provides a
+ ** pointer to a control block.
+ **----------------------------------------------------------------
+ */
+ Scsi_Cmnd *cmd; /* SCSI command */
+ u_long tlimit; /* Deadline for this job */
+ int data_len; /* Total data length */
+
+ /*----------------------------------------------------------------
+ ** Message areas.
+ ** We prepare a message to be sent after selection.
+ ** We may use a second one if the command is rescheduled
+ ** due to CHECK_CONDITION or QUEUE FULL status.
+ ** Contents are IDENTIFY and SIMPLE_TAG.
+ ** While negotiating sync or wide transfer,
+ ** a SDTR or WDTR message is appended.
+ **----------------------------------------------------------------
+ */
+ u_char scsi_smsg [8];
+ u_char scsi_smsg2[8];
+
+ /*----------------------------------------------------------------
+ ** Other fields.
+ **----------------------------------------------------------------
+ */
+ u_long p_ccb; /* BUS address of this CCB */
+ u_char sensecmd[6]; /* Sense command */
+ u_char tag; /* Tag for this transfer */
+ /* 255 means no tag */
+ u_char target;
+ u_char lun;
+ u_char queued;
+ u_char auto_sense;
+ ccb_p link_ccb; /* Host adapter CCB chain */
+ ccb_p link_ccbh; /* Host adapter CCB hash chain */
+ XPT_QUEHEAD link_ccbq; /* Link to unit CCB queue */
+ u_int32 startp; /* Initial data pointer */
+};
+
+#define CCB_PHYS(cp,lbl) (cp->p_ccb + offsetof(struct ccb, lbl))
+
+
+/*========================================================================
+**
+** Declaration of structs: NCR device descriptor
+**
+**========================================================================
+*/
+struct ncb {
+ /*----------------------------------------------------------------
+ ** Idle task and invalid task actions and their bus
+ ** addresses.
+ **----------------------------------------------------------------
+ */
+ struct action idletask;
+ struct action notask;
+ struct action bad_i_t_l;
+ struct action bad_i_t_l_q;
+ u_long p_idletask;
+ u_long p_notask;
+ u_long p_bad_i_t_l;
+ u_long p_bad_i_t_l_q;
+
+ /*----------------------------------------------------------------
+ ** Dummy lun table to protect us against target returning bad
+ ** lun number on reselection.
+ **----------------------------------------------------------------
+ */
+ u_int32 *badluntbl; /* Table physical address */
+ u_int32 resel_badlun; /* SCRIPT handler BUS address */
+
+ /*----------------------------------------------------------------
+ ** Bit 32-63 of the on-chip RAM bus address in LE format.
+ ** The START_RAM64 script loads the MMRS and MMWS from this
+ ** field.
+ **----------------------------------------------------------------
+ */
+ u_int32 scr_ram_seg;
+
+ /*----------------------------------------------------------------
+ ** CCBs management queues.
+ **----------------------------------------------------------------
+ */
+ Scsi_Cmnd *waiting_list; /* Commands waiting for a CCB */
+ /* when lcb is not allocated. */
+ Scsi_Cmnd *done_list; /* Commands waiting for done() */
+ /* callback to be invoked. */
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+ spinlock_t smp_lock; /* Lock for SMP threading */
+#endif
+
+ /*----------------------------------------------------------------
+ ** Chip and controller indentification.
+ **----------------------------------------------------------------
+ */
+ int unit; /* Unit number */
+ char chip_name[8]; /* Chip name */
+ char inst_name[16]; /* ncb instance name */
+
+ /*----------------------------------------------------------------
+ ** Initial value of some IO register bits.
+ ** These values are assumed to have been set by BIOS, and may
+ ** be used for probing adapter implementation differences.
+ **----------------------------------------------------------------
+ */
+ u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4,
+ sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4;
+
+ /*----------------------------------------------------------------
+ ** Actual initial value of IO register bits used by the
+ ** driver. They are loaded at initialisation according to
+ ** features that are to be enabled.
+ **----------------------------------------------------------------
+ */
+ u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4,
+ rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1;
+
+ /*----------------------------------------------------------------
+ ** Target data.
+ ** Target control block bus address array used by the SCRIPT
+ ** on reselection.
+ **----------------------------------------------------------------
+ */
+ struct tcb target[MAX_TARGET];
+ u_int32 *targtbl;
+
+ /*----------------------------------------------------------------
+ ** Virtual and physical bus addresses of the chip.
+ **----------------------------------------------------------------
+ */
+ u_long base_va; /* MMIO base virtual address */
+ u_long base_ba; /* MMIO base bus address */
+ u_long base_io; /* IO space base address */
+ u_long base_ws; /* (MM)IO window size */
+ u_long base2_ba; /* On-chip RAM bus address. */
+ u_int irq; /* IRQ number */
+ volatile /* Pointer to volatile for */
+ struct ncr_reg *reg; /* memory mapped IO. */
+
+ /*----------------------------------------------------------------
+ ** SCRIPTS virtual and physical bus addresses.
+ ** 'script' is loaded in the on-chip RAM if present.
+ ** 'scripth' stays in main memory for all chips except the
+ ** 53C896 that provides 8K on-chip RAM.
+ **----------------------------------------------------------------
+ */
+ struct script *script0; /* Copies of script and scripth */
+ struct scripth *scripth0; /* relocated for this ncb. */
+ u_long p_script; /* Actual script and scripth */
+ u_long p_scripth; /* bus addresses. */
+ u_long p_scripth0;
+
+ /*----------------------------------------------------------------
+ ** General controller parameters and configuration.
+ **----------------------------------------------------------------
+ */
+ u_short device_id; /* PCI device id */
+ u_char revision_id; /* PCI device revision id */
+ u_int features; /* Chip features map */
+ u_char myaddr; /* SCSI id of the adapter */
+ u_char maxburst; /* log base 2 of dwords burst */
+ u_char maxwide; /* Maximum transfer width */
+ u_char minsync; /* Minimum sync period factor */
+ u_char maxsync; /* Maximum sync period factor */
+ u_char maxoffs; /* Max scsi offset */
+ u_char multiplier; /* Clock multiplier (1,2,4) */
+ u_char clock_divn; /* Number of clock divisors */
+ u_long clock_khz; /* SCSI clock frequency in KHz */
+
+ /*----------------------------------------------------------------
+ ** Start queue management.
+ ** It is filled up by the host processor and accessed by the
+ ** SCRIPTS processor in order to start SCSI commands.
+ **----------------------------------------------------------------
+ */
+ u_int32 *squeue; /* Start queue */
+ u_short squeueput; /* Next free slot of the queue */
+ u_short actccbs; /* Number of allocated CCBs */
+ u_short queuedepth; /* Start queue depth */
+
+ /*----------------------------------------------------------------
+ ** Command completion queue.
+ ** It is the same size as the start queue to avoid overflow.
+ **----------------------------------------------------------------
+ */
+ u_short dqueueget; /* Next position to scan */
+ u_int32 *dqueue; /* Completion (done) queue */
+
+ /*----------------------------------------------------------------
+ ** Timeout handler.
+ **----------------------------------------------------------------
+ */
+ struct timer_list timer; /* Timer handler link header */
+ u_long lasttime;
+ u_long settle_time; /* Resetting the SCSI BUS */
+
+ /*----------------------------------------------------------------
+ ** Debugging and profiling.
+ **----------------------------------------------------------------
+ */
+ struct ncr_reg regdump; /* Register dump */
+ u_long regtime; /* Time it has been done */
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ struct profile profile; /* Profiling data */
+#endif
+
+ /*----------------------------------------------------------------
+ ** Miscellaneous buffers accessed by the scripts-processor.
+ ** They shall be DWORD aligned, because they may be read or
+ ** written with a script command.
+ **----------------------------------------------------------------
+ */
+ u_char msgout[8]; /* Buffer for MESSAGE OUT */
+ u_char msgin [8]; /* Buffer for MESSAGE IN */
+ u_int32 lastmsg; /* Last SCSI message sent */
+ u_char scratch; /* Scratch for SCSI receive */
+
+ /*----------------------------------------------------------------
+ ** Miscellaneous configuration and status parameters.
+ **----------------------------------------------------------------
+ */
+ u_char scsi_mode; /* Current SCSI BUS mode */
+ u_char order; /* Tag order to use */
+ u_char verbose; /* Verbosity for this controller*/
+ u_int32 ncr_cache; /* Used for cache test at init. */
+
+ /*----------------------------------------------------------------
+ ** CCB lists and queue.
+ **----------------------------------------------------------------
+ */
+ ccb_p ccbh[CCB_HASH_SIZE]; /* CCB hashed by DSA value */
+ struct ccb *ccbc; /* CCB chain */
+ XPT_QUEHEAD free_ccbq; /* Queue of available CCBs */
+
+ /*----------------------------------------------------------------
+ ** We need the LCB in order to handle disconnections and
+ ** to count active CCBs for task management. So, we use
+ ** a unique CCB for LUNs we donnot have the LCB yet.
+ ** This queue normally should have at most 1 element.
+ **----------------------------------------------------------------
+ */
+ XPT_QUEHEAD b0_ccbq;
+
+ /*----------------------------------------------------------------
+ ** We use a different scatter function for 896 rev 1.
+ **----------------------------------------------------------------
+ */
+ int (*scatter) (ccb_p, Scsi_Cmnd *);
+
+ /*----------------------------------------------------------------
+ ** Fields that should be removed or changed.
+ **----------------------------------------------------------------
+ */
+ struct usrcmd user; /* Command from user */
+ u_char release_stage; /* Synchronisation stage on release */
+};
+
+#define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl))
+#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl))
+#define NCB_SCRIPTH0_PHYS(np,lbl) (np->p_scripth0+offsetof (struct scripth,lbl))
+
+/*==========================================================
+**
+**
+** Script for NCR-Processor.
+**
+** Use ncr_script_fill() to create the variable parts.
+** Use ncr_script_copy_and_bind() to make a copy and
+** bind to physical addresses.
+**
+**
+**==========================================================
+**
+** We have to know the offsets of all labels before
+** we reach them (for forward jumps).
+** Therefore we declare a struct here.
+** If you make changes inside the script,
+** DONT FORGET TO CHANGE THE LENGTHS HERE!
+**
+**----------------------------------------------------------
+*/
+
+/*
+** Script fragments which are loaded into the on-chip RAM
+** of 825A, 875, 876, 895 and 896 chips.
+*/
+struct script {
+ ncrcmd start [ 10];
+ ncrcmd getjob_begin [ 4];
+ ncrcmd getjob_end [ 4];
+ ncrcmd select [ 4];
+ ncrcmd wf_sel_done [ 2];
+ ncrcmd send_ident [ 2];
+ ncrcmd select2 [ 6];
+ ncrcmd command [ 2];
+ ncrcmd dispatch [ 26];
+ ncrcmd sel_no_cmd [ 10];
+ ncrcmd init [ 6];
+ ncrcmd clrack [ 4];
+ ncrcmd databreak [ 2];
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ncrcmd dataphase [ 4];
+#else
+ ncrcmd dataphase [ 2];
+#endif
+ ncrcmd status [ 8];
+ ncrcmd msg_in [ 2];
+ ncrcmd msg_in2 [ 16];
+ ncrcmd msg_bad [ 6];
+ ncrcmd complete [ 8];
+ ncrcmd complete2 [ 6];
+ ncrcmd done [ 14];
+ ncrcmd done_end [ 2];
+ ncrcmd save_dp [ 8];
+ ncrcmd restore_dp [ 4];
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ncrcmd disconnect [ 32];
+#else
+ ncrcmd disconnect [ 20];
+#endif
+ ncrcmd idle [ 2];
+ ncrcmd ungetjob [ 4];
+ ncrcmd reselect [ 4];
+ ncrcmd reselected [ 44];
+ ncrcmd resel_tag [ 6];
+ ncrcmd resel_go [ 6];
+ ncrcmd resel_notag [ 4];
+ ncrcmd resel_dsa [ 8];
+ ncrcmd data_in [MAX_SCATTERL * SCR_SG_SIZE];
+ ncrcmd data_in2 [ 4];
+ ncrcmd data_out [MAX_SCATTERL * SCR_SG_SIZE];
+ ncrcmd data_out2 [ 4];
+ ncrcmd pm0_data [ 16];
+ ncrcmd pm1_data [ 16];
+
+ /* Data area */
+ ncrcmd saved_dsa [ 1];
+ ncrcmd done_pos [ 1];
+ ncrcmd startpos [ 1];
+ ncrcmd targtbl [ 1];
+};
+
+/*
+** Script fragments which stay in main memory for all chips
+** except for the 896 that support 8K on-chip RAM.
+*/
+struct scripth {
+ ncrcmd start64 [ 2];
+ ncrcmd select_no_atn [ 4];
+ ncrcmd wf_sel_done_no_atn [ 4];
+ ncrcmd cancel [ 4];
+ ncrcmd msg_reject [ 8];
+ ncrcmd msg_ign_residue [ 24];
+ ncrcmd msg_extended [ 10];
+ ncrcmd msg_ext_2 [ 10];
+ ncrcmd msg_wdtr [ 14];
+ ncrcmd send_wdtr [ 4];
+ ncrcmd msg_ext_3 [ 10];
+ ncrcmd msg_sdtr [ 14];
+ ncrcmd send_sdtr [ 4];
+ ncrcmd nego_bad_phase [ 4];
+ ncrcmd msg_out_abort [ 12];
+ ncrcmd msg_out [ 6];
+ ncrcmd msg_out_done [ 4];
+ ncrcmd no_data [ 16];
+#if MAX_SCATTERH != 0
+ ncrcmd hdata_in [MAX_SCATTERH * SCR_SG_SIZE];
+ ncrcmd hdata_in2 [ 2];
+ ncrcmd hdata_out [MAX_SCATTERH * SCR_SG_SIZE];
+ ncrcmd hdata_out2 [ 2];
+#endif
+ ncrcmd abort_resel [ 16];
+ ncrcmd resend_ident [ 4];
+ ncrcmd ident_break [ 4];
+ ncrcmd ident_break_atn [ 4];
+ ncrcmd sdata_in [ 6];
+ ncrcmd data_io [ 2];
+ ncrcmd data_io_com [ 8];
+ ncrcmd data_io_out [ 10];
+ ncrcmd bad_identify [ 12];
+ ncrcmd bad_i_t_l [ 4];
+ ncrcmd bad_i_t_l_q [ 4];
+ ncrcmd bad_status [ 10];
+ ncrcmd tweak_pmj [ 12];
+ ncrcmd pm_handle [ 20];
+ ncrcmd pm_handle1 [ 4];
+ ncrcmd pm_save [ 4];
+ ncrcmd pm0_save [ 10];
+ ncrcmd pm1_save [ 10];
+
+ /* Data area */
+ ncrcmd pm0_data_addr [ 1];
+ ncrcmd pm1_data_addr [ 1];
+ /* End of data area */
+
+ ncrcmd start_ram [ 1];
+ ncrcmd script0_ba [ 4];
+
+ ncrcmd start_ram64 [ 3];
+ ncrcmd script0_ba64 [ 3];
+ ncrcmd scripth0_ba64 [ 6];
+ ncrcmd ram_seg64 [ 1];
+
+ ncrcmd snooptest [ 6];
+ ncrcmd snoopend [ 2];


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

+** Function headers.
+**
+**
+**==========================================================
+*/
+
+static ccb_p ncr_alloc_ccb (ncb_p np);
+static void ncr_complete (ncb_p np, ccb_p cp);
+static void ncr_exception (ncb_p np);
+static void ncr_free_ccb (ncb_p np, ccb_p cp);
+static ccb_p ncr_ccb_from_dsa(ncb_p np, u_long dsa);
+static void ncr_init_tcb (ncb_p np, u_char tn);
+static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln);
+static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln,
+ u_char *inq_data);
+static void ncr_getclock (ncb_p np, int mult);
+static void ncr_selectclock (ncb_p np, u_char scntl3);
+static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln);
+static void ncr_init (ncb_p np, int reset, char * msg, u_long code);
+static void ncr_int_sbmc (ncb_p np);
+static void ncr_int_par (ncb_p np, u_short sist);
+static void ncr_int_ma (ncb_p np);
+static void ncr_int_sir (ncb_p np);
+static void ncr_int_sto (ncb_p np);
+static void ncr_int_udc (ncb_p np);
+static u_long ncr_lookup (char* id);
+static void ncr_negotiate (struct ncb* np, struct tcb* tp);
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+static void ncb_profile (ncb_p np, ccb_p cp);
+#endif
+static void ncr_script_copy_and_bind
+ (ncb_p np, ncrcmd *src, ncrcmd *dst, int len);
+static void ncr_script_fill (struct script * scr, struct scripth * scripth);
+static int ncr_scatter_896R1 (ccb_p cp, Scsi_Cmnd *cmd);
+static int ncr_scatter (ccb_p cp, Scsi_Cmnd *cmd);
+static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p);
+static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer);
+static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln);
+static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack);
+static int ncr_show_msg (u_char * msg);
+static int ncr_snooptest (ncb_p np);
+static void ncr_timeout (ncb_p np);
+static void ncr_wakeup (ncb_p np, u_long code);
+static int ncr_wakeup_done (ncb_p np);
+static void ncr_start_next_ccb (ncb_p np, lcb_p lp, int maxn);
+static void ncr_put_start_queue(ncb_p np, ccb_p cp);
+static void ncr_soft_reset (ncb_p np);
+static void ncr_start_reset (ncb_p np);
+static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay);
+
+#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
+static void ncr_usercmd (ncb_p np);
+#endif
+
+static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device);
+static void ncr_free_resources(ncb_p np);
+
+static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd);
+static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd);


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 17'
echo 'File patch-2.2.6 is continued in part 18'
echo 18 > _shar_seq_.tmp

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part20

#!/bin/sh
# this is part 20 of a 34 - part archive


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

if test "$Scheck" != 20; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

+** Misused to keep the driver running when
+** interrupts are not configured correctly.
+**
+**----------------------------------------------------------
+*/
+


+static void ncr_timeout (ncb_p np)

+{
+ u_long thistime = jiffies;
+
+ /*
+ ** If release process in progress, let's go
+ ** Set the release stage from 1 to 2 to synchronize
+ ** with the release process.
+ */
+
+ if (np->release_stage) {
+ if (np->release_stage == 1) np->release_stage = 2;
+ return;
+ }
+
+ np->timer.expires = jiffies + SCSI_NCR_TIMER_INTERVAL;
+ add_timer(&np->timer);
+
+ /*
+ ** If we are resetting the ncr, wait for settle_time before
+ ** clearing it. Then command processing will be resumed.
+ */
+ if (np->settle_time) {
+ if (np->settle_time <= thistime) {
+ if (bootverbose > 1)
+ printk("%s: command processing resumed\n", ncr_name(np));
+ np->settle_time = 0;
+ requeue_waiting_list(np);
+ }
+ return;
+ }
+
+ /*
+ ** Nothing to do for now, but that may come.
+ */
+ if (np->lasttime + 4*HZ < thistime) {
+ np->lasttime = thistime;
+ }
+
+#ifdef SCSI_NCR_BROKEN_INTR
+ if (INB(nc_istat) & (INTF|SIP|DIP)) {
+
+ /*
+ ** Process pending interrupts.
+ */
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("{");
+ ncr_exception (np);
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("}");
+ }
+#endif /* SCSI_NCR_BROKEN_INTR */
+}
+
+/*==========================================================
+**
+** log message for real hard errors
+**
+** "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)."
+** " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf."
+**
+** exception register:
+** ds: dstat
+** si: sist
+**
+** SCSI bus lines:
+** so: control lines as driver by NCR.
+** si: control lines as seen by NCR.
+** sd: scsi data lines as seen by NCR.
+**
+** wide/fastmode:
+** sxfer: (see the manual)
+** scntl3: (see the manual)
+**
+** current script command:
+** dsp: script adress (relative to start of script).
+** dbc: first word of script command.
+**
+** First 16 register of the chip:
+** r0..rf
+**
+**==========================================================
+*/
+
+static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat)
+{
+ u_int32 dsp;
+ int script_ofs;
+ int script_size;
+ char *script_name;
+ u_char *script_base;
+ int i;
+
+ dsp = INL (nc_dsp);
+
+ if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) {
+ script_ofs = dsp - np->p_script;
+ script_size = sizeof(struct script);
+ script_base = (u_char *) np->script0;
+ script_name = "script";
+ }
+ else if (np->p_scripth < dsp &&
+ dsp <= np->p_scripth + sizeof(struct scripth)) {
+ script_ofs = dsp - np->p_scripth;
+ script_size = sizeof(struct scripth);
+ script_base = (u_char *) np->scripth0;
+ script_name = "scripth";
+ } else {
+ script_ofs = dsp;
+ script_size = 0;
+ script_base = 0;
+ script_name = "mem";
+ }
+
+ printk ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n",
+ ncr_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
+ (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl),
+ (unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs,
+ (unsigned)INL (nc_dbc));
+
+ if (((script_ofs & 3) == 0) &&
+ (unsigned)script_ofs < script_size) {
+ printk ("%s: script cmd = %08x\n", ncr_name(np),
+ scr_to_cpu((int) *(ncrcmd *)(script_base + script_ofs)));
+ }
+
+ printk ("%s: regdump:", ncr_name(np));
+ for (i=0; i<16;i++)
+ printk (" %02x", (unsigned)INB_OFF(i));
+ printk (".\n");
+}
+
+/*============================================================
+**
+** ncr chip exception handler.
+**
+**============================================================
+**
+** In normal situations, interrupt conditions occur one at
+** a time. But when something bad happens on the SCSI BUS,
+** the chip may raise several interrupt flags before
+** stopping and interrupting the CPU. The additionnal
+** interrupt flags are stacked in some extra registers
+** after the SIP and/or DIP flag has been raised in the
+** ISTAT. After the CPU has read the interrupt condition
+** flag from SIST or DSTAT, the chip unstacks the other
+** interrupt flags and sets the corresponding bits in
+** SIST or DSTAT. Since the chip starts stacking once the
+** SIP or DIP flag is set, there is a small window of time
+** where the stacking does not occur.
+**
+** Typically, multiple interrupt conditions may happen in
+** the following situations:
+**
+** - SCSI parity error + Phase mismatch (PAR|MA)
+** When an parity error is detected in input phase
+** and the device switches to msg-in phase inside a
+** block MOV.
+** - SCSI parity error + Unexpected disconnect (PAR|UDC)
+** When a stupid device does not want to handle the
+** recovery of an SCSI parity error.
+** - Some combinations of STO, PAR, UDC, ...
+** When using non compliant SCSI stuff, when user is
+** doing non compliant hot tampering on the BUS, when
+** something really bad happens to a device, etc ...
+**
+** The heuristic suggested by SYMBIOS to handle
+** multiple interrupts is to try unstacking all
+** interrupts conditions and to handle them on some
+** priority based on error severity.
+** This will work when the unstacking has been
+** successful, but we cannot be 100 % sure of that,
+** since the CPU may have been faster to unstack than
+** the chip is able to stack. Hmmm ... But it seems that
+** such a situation is very unlikely to happen.
+**
+** If this happen, for example STO catched by the CPU
+** then UDC happenning before the CPU have restarted
+** the SCRIPTS, the driver may wrongly complete the
+** same command on UDC, since the SCRIPTS didn't restart
+** and the DSA still points to the same command.
+** We avoid this situation by setting the DSA to an
+** invalid value when the CCB is completed and before
+** restarting the SCRIPTS.
+**
+** Another issue is that we need some section of our
+** recovery procedures to be somehow uninterruptible and
+** that the SCRIPTS processor does not provides such a
+** feature. For this reason, we handle recovery preferently
+** from the C code and check against some SCRIPTS
+** critical sections from the C code.
+**
+** Hopefully, the interrupt handling of the driver is now
+** able to resist to weird BUS error conditions, but donnot
+** ask me for any guarantee that it will never fail. :-)
+** Use at your own decision and risk.
+**
+**============================================================
+*/
+
+void ncr_exception (ncb_p np)
+{
+ u_char istat, istatc;
+ u_char dstat;
+ u_short sist;
+ int i;
+
+#ifdef SCSI_NCR_OPTIMIZE_896_1
+ /*
+ ** This optimization when used with a 896 that handles
+ ** phase mismatch from the SCRIPTS allows to only do
+ ** PCI memory writes transactions from the CPU and so to
+ ** take advantage of PCI posted writes.
+ ** Who wants his 500 MHz CPU to wait several micro-seconds
+ ** for the PCI BUS to be granted when this can be avoided?
+ ** I don't, even for my slow 233 MHz PII. :-)
+ **
+ ** We assume we have been called for command completion.
+ ** If no completion found, go with normal handling.
+ ** Ordering is ensured by the SCRIPTS performing a read
+ ** from main memory prior to raising INTFLY.
+ ** We have to raise SIGP since the chip may be currently
+ ** going to a wait reselect instruction. IMO, SIGP should
+ ** not be clearable in ISTAT since it can be polled and
+ ** cleared by reading CTEST2. This tiny chip misdesign is a
+ ** penalty here.
+ **
+ ** The MA interrupt and interrupt sharing may also have
+ ** adverse effects on this optimization, so we only want
+ ** to use it if it is enabled by user.
+ ** (BTW, this optimization seems to even have some goodness
+ ** with my 895 that unfortunately suffers of the MA int.).
+ */
+ if (driver_setup.optimize & 1) {
+ OUTB(nc_istat, (INTF | SIGP));
+ if (ncr_wakeup_done (np)) {
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_fly;
+#endif
+ return;
+ }
+ }
+#endif /* SCSI_NCR_OPTIMIZE_896_1 */
+
+ /*
+ ** interrupt on the fly ?
+ */
+ istat = INB (nc_istat);
+ if (istat & INTF) {
+ OUTB (nc_istat, (istat & SIGP) | INTF);
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("F ");
+ (void)ncr_wakeup_done (np);
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_fly;
+#endif
+ };
+
+ if (!(istat & (SIP|DIP)))
+ return;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_int;
+#endif
+
+#if 0 /* We should never get this one */
+ if (istat & CABRT)
+ OUTB (nc_istat, CABRT);
+#endif
+
+ /*
+ ** Steinbach's Guideline for Systems Programming:
+ ** Never test for an error condition you don't know how to handle.
+ */
+
+ /*========================================================
+ ** PAR and MA interrupts may occur at the same time,
+ ** and we need to know of both in order to handle
+ ** this situation properly. We try to unstack SCSI
+ ** interrupts for that reason. BTW, I dislike a LOT
+ ** such a loop inside the interrupt routine.
+ ** Even if DMA interrupt stacking is very unlikely to
+ ** happen, we also try unstacking these ones, since
+ ** this has no performance impact.
+ **=========================================================
+ */
+ sist = 0;
+ dstat = 0;
+ istatc = istat;
+ do {
+ if (istatc & SIP)
+ sist |= INW (nc_sist);
+ if (istatc & DIP)
+ dstat |= INB (nc_dstat);
+ istatc = INB (nc_istat);
+ istat |= istatc;
+ } while (istatc & (SIP|DIP));
+
+ if (DEBUG_FLAGS & DEBUG_TINY)
+ printk ("<%d|%x:%x|%x:%x>",
+ (int)INB(nc_scr0),
+ dstat,sist,
+ (unsigned)INL(nc_dsp),
+ (unsigned)INL(nc_dbc));
+
+ /*========================================================
+ ** First, interrupts we want to service cleanly.
+ **
+ ** Phase mismatch (MA) is the most frequent interrupt
+ ** for chip earlier than the 896 and so we have to service
+ ** it as quickly as possible.
+ ** A SCSI parity error (PAR) may be combined with a phase
+ ** mismatch condition (MA).
+ ** Programmed interrupts (SIR) are used to call the C code
+ ** from SCRIPTS.
+ ** The single step interrupt (SSI) is not used in this
+ ** driver.
+ **=========================================================
+ */
+
+ if (!(sist & (STO|GEN|HTH|SGE|UDC|SBMC|RST)) &&
+ !(dstat & (MDPE|BF|ABRT|IID))) {
+ if (sist & PAR) ncr_int_par (np, sist);
+ else if (sist & MA) ncr_int_ma (np);
+ else if (dstat & SIR) ncr_int_sir (np);
+ else if (dstat & SSI) OUTONB (nc_dcntl, (STD|NOCOM));
+ else goto unknown_int;
+ return;
+ };
+
+ /*========================================================
+ ** Now, interrupts that donnot happen in normal
+ ** situations and that we may need to recover from.
+ **
+ ** On SCSI RESET (RST), we reset everything.
+ ** On SCSI BUS MODE CHANGE (SBMC), we complete all
+ ** active CCBs with RESET status, prepare all devices
+ ** for negotiating again and restart the SCRIPTS.
+ ** On STO and UDC, we complete the CCB with the corres-
+ ** ponding status and restart the SCRIPTS.
+ **=========================================================
+ */
+
+ if (sist & RST) {
+ ncr_init (np, 1, bootverbose ? "scsi reset" : NULL, HS_RESET);
+ return;
+ };
+
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+
+ if (!(sist & (GEN|HTH|SGE)) &&
+ !(dstat & (MDPE|BF|ABRT|IID))) {
+ if (sist & SBMC) ncr_int_sbmc (np);
+ else if (sist & STO) ncr_int_sto (np);
+ else if (sist & UDC) ncr_int_udc (np);
+ else goto unknown_int;
+ return;
+ };
+
+ /*=========================================================
+ ** Now, interrupts we are not able to recover cleanly.
+ **
+ ** Do the register dump.
+ ** Log message for hard errors.
+ ** Reset everything.
+ **=========================================================
+ */
+ if (jiffies - np->regtime > 10*HZ) {
+ np->regtime = jiffies;
+ for (i = 0; i<sizeof(np->regdump); i++)
+ ((char*)&np->regdump)[i] = INB_OFF(i);
+ np->regdump.nc_dstat = dstat;
+ np->regdump.nc_sist = sist;
+ };
+
+ ncr_log_hard_error(np, sist, dstat);
+
+ if ((sist & (GEN|HTH|SGE)) ||
+ (dstat & (MDPE|BF|ABRT|IID))) {
+ ncr_start_reset(np);
+ return;
+ };
+
+unknown_int:
+ /*=========================================================
+ ** We just miss the cause of the interrupt. :(
+ ** Print a message. The timeout will do the real work.
+ **=========================================================
+ */
+ printk( "%s: unknown interrupt(s) ignored, "
+ "ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n",
+ ncr_name(np), istat, dstat, sist);


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

+** generic recovery from scsi interrupt
+**
+**==========================================================
+**
+** The doc says that when the chip gets an SCSI interrupt,
+** it tries to stop in an orderly fashion, by completing
+** an instruction fetch that had started or by flushing
+** the DMA fifo for a write to memory that was executing.
+** Such a fashion is not enough to know if the instruction
+** that was just before the current DSP value has been
+** executed or not.
+**
+** There are 3 small SCRIPTS sections that deal with the
+** start queue and the done queue that may break any
+** assomption from the C code if we are interrupted
+** inside, so we reset if it happens. Btw, since these
+** SCRIPTS sections are executed while the SCRIPTS hasn't
+** started SCSI operations, it is very unlikely to happen.
+**
+** All the driver data structures are supposed to be
+** allocated from the same 4 GB memory window, so there
+** is a 1 to 1 relationship between DSA and driver data
+** structures. Since we are careful :) to invalidate the
+** DSA when we complete a command or when the SCRIPTS
+** pushes a DSA into a queue, we can trust it when it
+** points to a CCB.
+**
+**----------------------------------------------------------
+*/
+static void ncr_recover_scsi_int (ncb_p np, u_char hsts)
+{
+ u_int32 dsp = INL (nc_dsp);
+ u_int32 dsa = INL (nc_dsa);
+ u_char scntl1 = INB (nc_scntl1);
+ ccb_p cp = ncr_ccb_from_dsa(np, dsa);
+
+ /*
+ ** If we are connected to the SCSI BUS, we only
+ ** can reset the BUS.
+ */
+ if (scntl1 & ISCON)
+ goto reset_all;
+
+ /*
+ ** If we haven't been interrupted inside the SCRIPTS
+ ** critical pathes, we can safely restart the SCRIPTS
+ ** and trust the DSA value if it matches a CCB.
+ */
+ if ((!(dsp > NCB_SCRIPT_PHYS (np, getjob_begin) &&
+ dsp < NCB_SCRIPT_PHYS (np, getjob_end) + 1)) &&
+ (!(dsp > NCB_SCRIPT_PHYS (np, ungetjob) &&
+ dsp < NCB_SCRIPT_PHYS (np, reselect) + 1)) &&
+ (!(dsp > NCB_SCRIPT_PHYS (np, done) &&
+ dsp < NCB_SCRIPT_PHYS (np, done_end) + 1))) {
+ if (cp) {
+ cp->host_status = hsts;
+ ncr_complete (np, cp);
+ }
+ OUTL (nc_dsa, DSA_INVALID);
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
+ }
+ else
+ goto reset_all;
+
+ return;
+
+reset_all:
+ ncr_start_reset(np);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for selection timeout
+**
+**==========================================================
+**
+** There seems to be a bug in the 53c810.
+** Although a STO-Interrupt is pending,
+** it continues executing script commands.
+** But it will fail and interrupt (IID) on
+** the next instruction where it's looking
+** for a valid phase.
+**
+**----------------------------------------------------------
+*/
+
+void ncr_int_sto (ncb_p np)
+{
+ u_int32 dsp = INL (nc_dsp);
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("T");
+
+ if (dsp == NCB_SCRIPT_PHYS (np, wf_sel_done) + 8 ||
+ dsp == NCB_SCRIPTH_PHYS (np, wf_sel_done_no_atn) + 8 ||
+ !(driver_setup.recovery & 1))
+ ncr_recover_scsi_int(np, HS_SEL_TIMEOUT);
+ else
+ ncr_start_reset(np);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for unexpected disconnect
+**
+**==========================================================
+**
+**----------------------------------------------------------
+*/
+void ncr_int_udc (ncb_p np)
+{
+ printk ("%s: unexpected disconnect\n", ncr_name(np));
+ ncr_recover_scsi_int(np, HS_UNEXPECTED);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for SCSI bus mode change
+**
+**==========================================================
+**
+** spi2-r12 11.2.3 says a transceiver mode change must
+** generate a reset event and a device that detects a reset
+** event shall initiate a hard reset. It says also that a
+** device that detects a mode change shall set data transfer
+** mode to eight bit asynchronous, etc...
+** So, just resetting should be enough.
+**
+**
+**----------------------------------------------------------
+*/
+


+static void ncr_int_sbmc (ncb_p np)

+{
+ u_char scsi_mode = INB (nc_stest4) & SMODE;
+
+ printk("%s: SCSI bus mode change from %x to %x.\n",
+ ncr_name(np), np->scsi_mode, scsi_mode);
+
+ np->scsi_mode = scsi_mode;
+
+
+ /*
+ ** Suspend command processing for 1 second and
+ ** reinitialize all except the chip.
+ */
+ np->settle_time = jiffies + HZ;
+ ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for SCSI parity error.
+**
+**==========================================================
+**
+** When the chip detects a SCSI parity error and is
+** currently executing a (CH)MOV instruction, it does
+** not interrupt immediately, but tries to finish the
+** transfer of the current scatter entry before
+** interrupting. The following situations may occur:
+**
+** - The complete scatter entry has been transferred
+** without the device having changed phase.
+** The chip will then interrupt with the DSP pointing
+** to the instruction that follows the MOV.
+**
+** - A phase mismatch occurs before the MOV finished
+** and phase errors are to be handled by the C code.
+** The chip will then interrupt with both PAR and MA
+** conditions set.
+**
+** - A phase mismatch occurs before the MOV finished
+** and phase errors are to be handled by SCRIPTS (896).
+** The chip will load the DSP with the phase mismatch
+** JUMP address and interrupt the host processor.
+**
+**----------------------------------------------------------
+*/
+


+static void ncr_int_par (ncb_p np, u_short sist)

+{
+ u_char hsts = INB (HS_PRT);
+ u_int32 dsp = INL (nc_dsp);
+ u_int32 dbc = INL (nc_dbc);
+ u_int32 dsa = INL (nc_dsa);
+ u_char sbcl = INB (nc_sbcl);
+ u_char cmd = dbc >> 24;
+ int phase = cmd & 7;
+
+ printk("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n",
+ ncr_name(np), hsts, dbc, sbcl);
+
+ /*
+ ** Check that the chip is connected to the SCSI BUS.
+ */
+ if (!(INB (nc_scntl1) & ISCON)) {
+ if (!(driver_setup.recovery & 1)) {
+ ncr_recover_scsi_int(np, HS_FAIL);
+ return;
+ }
+ goto reset_all;
+ }
+
+ /*
+ ** If the nexus is not clearly identified, reset the bus.
+ ** We will try to do better later.
+ */
+ if (!ncr_ccb_from_dsa(np, dsa))
+ goto reset_all;
+
+ /*
+ ** Check instruction was a MOV, direction was INPUT and
+ ** ATN is asserted.
+ */
+ if ((cmd & 0xc0) || !(phase & 1) || !(sbcl & 0x8))
+ goto reset_all;
+
+ /*
+ ** Keep track of the parity error.
+ */
+ OUTONB (HF_PRT, HF_PAR_ERR);
+
+ /*
+ ** Prepare the message to send to the device.
+ */
+ np->msgout[0] = (phase == 7) ? M_PARITY : M_ID_ERROR;
+
+ /*
+ ** If the old phase was DATA IN phase, we have to deal with
+ ** the 3 situations described above.
+ ** For other input phases (MSG IN and STATUS), the device
+ ** must resend the whole thing that failed parity checking
+ ** or signal error. So, jumping to dispatcher should be OK.
+ */
+ if (phase == 1) {
+ /* Phase mismatch handled by SCRIPTS */
+ if (dsp == NCB_SCRIPTH_PHYS (np, pm_handle))
+ OUTL (nc_dsp, dsp);
+ /* Phase mismatch handled by the C code */
+ else if (sist & MA)
+ ncr_int_ma (np);
+ /* No phase mismatch occurred */
+ else {
+ OUTL (nc_temp, dsp);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, databreak));
+ }
+ }
+ else
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
+ return;
+
+reset_all:
+ ncr_start_reset(np);
+ return;


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

+** ncr chip exception handler for phase errors.
+**
+**
+**==========================================================
+**
+** We have to construct a new transfer descriptor,
+** to transfer the rest of the current block.
+**
+**----------------------------------------------------------
+*/
+


+static void ncr_int_ma (ncb_p np)

+{
+ u_int32 dbc;
+ u_int32 rest;
+ u_int32 dsp;
+ u_int32 dsa;
+ u_int32 nxtdsp;
+ u_int32 *vdsp;
+ u_int32 oadr, olen;
+ u_int32 *tblp;
+ u_int32 newcmd;
+ u_int delta;
+ u_char cmd;
+ u_char hflags, hflags0;
+ struct pm_ctx *pm;
+ ccb_p cp;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_break;
+#endif
+
+ dsp = INL (nc_dsp);
+ dbc = INL (nc_dbc);
+ dsa = INL (nc_dsa);
+
+ cmd = dbc >> 24;
+ rest = dbc & 0xffffff;
+ delta = 0;
+
+ /*
+ ** locate matching cp.
+ */
+ cp = ncr_ccb_from_dsa(np, dsa);
+
+ /*
+ ** Donnot take into account dma fifo and various buffers in
+ ** DATA IN phase since the chip flushes everything before
+ ** raising the MA interrupt for interrupted INPUT phases.
+ */
+ if ((cmd & 7) != 1) {
+ u_int32 dfifo;
+ u_char ss0, ss2;
+
+ /*
+ ** Read DFIFO, CTEST[4-6] using 1 PCI bus ownership.
+ */
+ dfifo = INL(nc_dfifo);
+
+ /*
+ ** Calculate remaining bytes in DMA fifo.
+ ** (CTEST5 = dfifo >> 16)
+ */
+ if (dfifo & (DFS << 16))
+ delta = ((((dfifo >> 8) & 0x300) |
+ (dfifo & 0xff)) - rest) & 0x3ff;
+ else
+ delta = ((dfifo & 0xff) - rest) & 0x7f;
+
+ /*
+ ** The data in the dma fifo has not been transfered to
+ ** the target -> add the amount to the rest
+ ** and clear the data.
+ ** Check the sstat2 register in case of wide transfer.
+ */
+ rest += delta;
+ ss0 = INB (nc_sstat0);
+ if (ss0 & OLF) rest++;
+ if (ss0 & ORF) rest++;
+ if (cp && (cp->phys.select.sel_scntl3 & EWS)) {
+ ss2 = INB (nc_sstat2);
+ if (ss2 & OLF1) rest++;
+ if (ss2 & ORF1) rest++;
+ };
+
+ /*
+ ** Clear fifos.
+ */
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* scsi fifo */
+ };
+
+ /*
+ ** log the information
+ */
+
+ if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE))
+ printk ("P%x%x RL=%d D=%d ", cmd&7, INB(nc_sbcl)&7,
+ (unsigned) rest, (unsigned) delta);
+
+ /*
+ ** try to find the interrupted script command,
+ ** and the address at which to continue.
+ */
+ vdsp = 0;
+ nxtdsp = 0;
+ if (dsp > np->p_script &&
+ dsp <= np->p_script + sizeof(struct script)) {
+ vdsp = (u_int32 *)((char*)np->script0 + (dsp-np->p_script-8));
+ nxtdsp = dsp;
+ }
+ else if (dsp > np->p_scripth &&
+ dsp <= np->p_scripth + sizeof(struct scripth)) {
+ vdsp = (u_int32 *)((char*)np->scripth0 + (dsp-np->p_scripth-8));
+ nxtdsp = dsp;
+ }
+
+ /*
+ ** log the information
+ */
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ printk ("\nCP=%p DSP=%x NXT=%x VDSP=%p CMD=%x ",
+ cp, (unsigned)dsp, (unsigned)nxtdsp, vdsp, cmd);
+ };
+
+ if (!vdsp) {
+ printk ("%s: interrupted SCRIPT address not found.\n",
+ ncr_name (np));
+ goto reset_all;
+ }
+
+ if (!cp) {
+ printk ("%s: SCSI phase error fixup: CCB already dequeued.\n",
+ ncr_name (np));
+ goto reset_all;
+ }
+
+ /*
+ ** get old startaddress and old length.
+ */
+
+ oadr = scr_to_cpu(vdsp[1]);
+
+ if (cmd & 0x10) { /* Table indirect */
+ tblp = (u_int32 *) ((char*) &cp->phys + oadr);
+ olen = scr_to_cpu(tblp[0]);
+ oadr = scr_to_cpu(tblp[1]);
+ } else {
+ tblp = (u_int32 *) 0;
+ olen = scr_to_cpu(vdsp[0]) & 0xffffff;
+ };
+
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ printk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
+ (unsigned) (scr_to_cpu(vdsp[0]) >> 24),
+ tblp,
+ (unsigned) olen,
+ (unsigned) oadr);
+ };
+
+ /*
+ ** check cmd against assumed interrupted script command.
+ */
+
+ if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) {
+ PRINT_ADDR(cp->cmd);
+ printk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
+ (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
+
+ goto reset_all;
+ };
+
+ /*
+ ** if old phase not dataphase, leave here.
+ */
+
+ if (cmd & 0x06) {
+ PRINT_ADDR(cp->cmd);
+ printk ("phase change %x-%x %d@%08x resid=%d.\n",
+ cmd&7, INB(nc_sbcl)&7, (unsigned)olen,
+ (unsigned)oadr, (unsigned)rest);
+ goto unexpected_phase;
+ };
+
+ /*
+ ** Choose the correct PM save area.
+ **
+ ** Look at the PM_SAVE SCRIPT if you want to understand
+ ** this stuff. The equivalent code is implemented in
+ ** SCRIPTS for the 896 that is able to handle PM from
+ ** the SCRIPTS processor.
+ */
+
+ hflags0 = INB (HF_PRT);
+ hflags = hflags0;
+
+ if (hflags & (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED)) {
+ if (hflags & HF_IN_PM0)
+ nxtdsp = scr_to_cpu(cp->phys.pm0.ret);
+ else if (hflags & HF_IN_PM1)
+ nxtdsp = scr_to_cpu(cp->phys.pm1.ret);
+
+ if (hflags & HF_DP_SAVED)
+ hflags ^= HF_ACT_PM;
+ }
+
+ if (!(hflags & HF_ACT_PM)) {
+ pm = &cp->phys.pm0;
+ newcmd = NCB_SCRIPT_PHYS(np, pm0_data);
+ }
+ else {
+ pm = &cp->phys.pm1;
+ newcmd = NCB_SCRIPT_PHYS(np, pm1_data);
+ }
+
+ hflags &= ~(HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED);
+ if (hflags != hflags0)
+ OUTB (HF_PRT, hflags);
+
+ /*
+ ** fillin the phase mismatch context
+ */
+
+ pm->sg.addr = cpu_to_scr(oadr + olen - rest);
+ pm->sg.size = cpu_to_scr(rest);
+ pm->ret = cpu_to_scr(nxtdsp);
+
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ PRINT_ADDR(cp->cmd);
+ printk ("PM %x %x %x / %x %x %x.\n",
+ hflags0, hflags, newcmd,
+ (unsigned)scr_to_cpu(pm->sg.addr),
+ (unsigned)scr_to_cpu(pm->sg.size),
+ (unsigned)scr_to_cpu(pm->ret));
+ }
+
+ /*
+ ** fake the return address (to the patch).
+ ** and restart script processor at dispatcher.
+ */
+
+ OUTL (nc_temp, newcmd);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, databreak));
+ return;
+
+ /*
+ ** Unexpected phase changes that occurs when the current phase
+ ** is not a DATA IN or DATA OUT phase are due to error conditions.
+ ** Such event may only happen when the SCRIPTS is using a
+ ** multibyte SCSI MOVE.
+ **
+ ** Phase change Some possible cause
+ **
+ ** COMMAND --> MSG IN SCSI parity error detected by target.
+ ** COMMAND --> STATUS Bad command or refused by target.
+ ** MSG OUT --> MSG IN Message rejected by target.
+ ** MSG OUT --> COMMAND Bogus target that discards extended
+ ** negotiation messages.
+ **
+ ** The code below does not care of the new phase and so
+ ** trusts the target. Why to annoy it ?
+ ** If the interrupted phase is COMMAND phase, we restart at
+ ** dispatcher.
+ ** If a target does not get all the messages after selection,
+ ** the code assumes blindly that the target discards extended
+ ** messages and clears the negotiation status.
+ ** If the target does not want all our response to negotiation,
+ ** we force a SIR_NEGO_PROTO interrupt (it is a hack that avoids
+ ** bloat for such a should_not_happen situation).
+ ** In all other situation, we reset the BUS.
+ ** Are these assumptions reasonnable ? (Wait and see ...)
+ */
+unexpected_phase:
+ dsp -= 8;
+ nxtdsp = 0;
+
+ switch (cmd & 7) {
+ case 2: /* COMMAND phase */
+ nxtdsp = NCB_SCRIPT_PHYS (np, dispatch);
+ break;
+#if 0
+ case 3: /* STATUS phase */
+ nxtdsp = NCB_SCRIPT_PHYS (np, dispatch);
+ break;
+#endif
+ case 6: /* MSG OUT phase */
+ /*
+ ** If the device may want to use untagged when we want
+ ** tagged, we prepare an IDENTIFY without disc. granted,
+ ** since we will not be able to handle reselect.
+ ** Otherwise, we just don't care.
+ */
+ if (dsp == NCB_SCRIPT_PHYS (np, send_ident)) {
+ if (cp->tag != NO_TAG && olen - rest <= 3) {
+ cp->host_status = HS_BUSY;
+ np->msgout[0] = M_IDENTIFY | cp->lun;
+ nxtdsp = NCB_SCRIPTH_PHYS (np, ident_break_atn);
+ }
+ else
+ nxtdsp = NCB_SCRIPTH_PHYS (np, ident_break);
+ }
+ else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) ||
+ dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) {
+ nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase);
+ }
+ break;
+#if 0
+ case 7: /* MSG IN phase */
+ nxtdsp = NCB_SCRIPT_PHYS (np, clrack);
+ break;
+#endif
+ }
+
+ if (nxtdsp) {
+ OUTL (nc_dsp, nxtdsp);
+ return;
+ }
+
+reset_all:
+ ncr_start_reset(np);
+}
+
+/*==========================================================
+**
+** ncr chip handler for QUEUE FULL and CHECK CONDITION
+**
+**==========================================================
+**
+** On QUEUE FULL status, we set the actual tagged command
+** queue depth to the number of disconnected CCBs that is
+** hopefully a good value to avoid further QUEUE FULL.
+**
+** On CHECK CONDITION or COMMAND TERMINATED, we use the
+** CCB of the failed command for performing a REQUEST
+** SENSE SCSI command.
+**
+** We do not want to change the order commands will be
+** actually queued to the device after we received a
+** QUEUE FULL status. We also want to properly deal with
+** contingent allegiance condition. For these reasons,
+** we remove from the start queue all commands for this
+** LUN that haven't been yet queued to the device and
+** put them back in the correponding LUN queue, then
+** requeue the CCB that failed in front of the LUN queue.
+** I just hope this not to be performed too often. :)
+**
+**----------------------------------------------------------
+*/
+
+static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp)
+{
+ Scsi_Cmnd *cmd = cp->cmd;
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = tp->lp[cp->lun];
+ ccb_p cp2;
+ int busyccbs = 1;
+ u_int32 startp;
+ u_char s_status = INB (SS_PRT);
+
+ /*
+ ** Remove all CCBs queued to the chip for that LUN and put
+ ** them back in the LUN CCB wait queue.
+ */
+ if (lp) {
+ int i = np->squeueput;
+ int j = (INL (nc_scratcha) - vtobus(np->squeue)) / 4;
+ int k = np->squeueput;
+
+ busyccbs = lp->queuedccbs;
+ while (1) {
+ if (i == j)
+ break;
+ if (i == 0)
+ i = MAX_START*2;
+ i = i - 2;
+ cp2 = ncr_ccb_from_dsa(np, scr_to_cpu(np->squeue[i]));
+ if (!cp2)
+ continue;
+ if (cp2->target != cp->target || cp2->lun != cp->lun)
+ continue;
+ xpt_remque(&cp2->link_ccbq);
+ xpt_insque_head(&cp2->link_ccbq, &lp->wait_ccbq);
+ --lp->queuedccbs;
+ cp2->queued = 0;
+ np->squeue[i] = DSA_INVALID;
+ k = i;
+ }
+
+ /*
+ ** Requeue the interrupted CCB in front of
+ ** the LUN CCB wait queue.
+ */
+ xpt_remque(&cp->link_ccbq);
+ xpt_insque_head(&cp->link_ccbq, &lp->wait_ccbq);
+ --lp->queuedccbs;
+ cp->queued = 0;
+
+ /*
+ ** Repair the startqueue if necessary.
+ */
+ if (k != np->squeueput) {
+ j = k;
+ while (1) {
+ j += 2;
+ if (j >= MAX_START*2)
+ j = 0;
+ if (np->squeue[j] == DSA_INVALID)
+ continue;
+ np->squeue[k] = np->squeue[j];
+ if (j == np->squeueput)
+ break;
+ k += 2;
+ if (k >= MAX_START*2)
+ k = 0;
+ }
+ np->squeueput = k;
+ }
+ }
+
+ /*
+ ** Now we can restart the SCRIPTS processor safely.
+ */
+ MEMORY_BARRIER();
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
+
+ switch(s_status) {
+ default: /* Just for safety, should never happen */
+ case S_QUEUE_FULL:
+ if (!lp || !lp->queuedccbs) {
+ ncr_complete(np, cp);
+ break;
+ }
+ if (bootverbose >= 1) {
+ PRINT_ADDR(cmd);
+ printk ("QUEUE FULL! %d busy, %d disconnected CCBs\n",
+ busyccbs, lp->queuedccbs);
+ }
+ /*
+ ** Decrease number of tags to the number of
+ ** disconnected commands.
+ */
+ if (lp->queuedccbs < lp->numtags) {
+ lp->numtags = lp->queuedccbs;
+ lp->num_good = 0;
+ ncr_setup_tags (np, cp->target, cp->lun);
+ }
+ /*
+ ** Repair the offending CCB.
+ */
+ cp->phys.header.savep = cp->startp;
+ cp->host_status = HS_BUSY;
+ cp->scsi_status = S_ILLEGAL;
+ cp->host_flags &= HF_PM_TO_C;
+
+ break;
+
+ case S_TERMINATED:
+ case S_CHECK_COND:
+ /*
+ ** If we were requesting sense, give up.
+ */
+ if (cp->auto_sense) {
+ ncr_complete(np, cp);
+ break;
+ }
+
+ /*
+ ** Device returned CHECK CONDITION status.
+ ** Prepare all needed data strutures for getting
+ ** sense data.
+ */
+
+ /*
+ ** identify message
+ */
+ cp->scsi_smsg2[0] = M_IDENTIFY | cp->lun;
+ cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2));
+ cp->phys.smsg.size = cpu_to_scr(1);
+
+ /*
+ ** sense command
+ */
+ cp->phys.cmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd));
+ cp->phys.cmd.size = cpu_to_scr(6);
+
+ /*
+ ** patch requested size into sense command
+ */
+ cp->sensecmd[0] = 0x03;
+ cp->sensecmd[1] = cp->lun << 5;
+ cp->sensecmd[4] = sizeof(cmd->sense_buffer);
+
+ /*
+ ** sense data
+ */
+ cp->phys.sense.addr =
+ cpu_to_scr(vtobus (&cmd->sense_buffer[0]));
+ cp->phys.sense.size =
+ cpu_to_scr(sizeof(cmd->sense_buffer));
+
+ /*
+ ** requeue the command.
+ */
+ startp = cpu_to_scr(NCB_SCRIPTH_PHYS (np, sdata_in));
+
+ cp->phys.header.savep = startp;
+ cp->phys.header.goalp = startp + 24;
+ cp->phys.header.lastp = startp;
+ cp->phys.header.wgoalp = startp + 24;
+ cp->phys.header.wlastp = startp;
+
+ cp->host_status = HS_BUSY;
+ cp->scsi_status = S_ILLEGAL;
+ cp->host_flags = 0;
+ cp->auto_sense = s_status;
+
+ cp->phys.header.go.start =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, select));
+
+ /*
+ ** Select without ATN for quirky devices.
+ */
+ if (tp->quirks & QUIRK_NOMSG)
+ cp->phys.header.go.start =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, select_no_atn));
+
+ /*
+ ** If lp not yet allocated, requeue the command.
+ */
+ if (!lp)
+ ncr_put_start_queue(np, cp);
+ break;
+ }
+
+ /*
+ ** requeue awaiting scsi commands for this lun.
+ */
+ if (lp)
+ ncr_start_next_ccb(np, lp, 1);
+
+ return;


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

+** ncr chip exception handler for programmed interrupts.


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

+static int ncr_show_msg (u_char * msg)

+{
+ u_char i;
+ printk ("%x",*msg);
+ if (*msg==M_EXTENDED) {
+ for (i=1;i<8;i++) {
+ if (i-1>msg[1]) break;
+ printk ("-%x",msg[i]);
+ };
+ return (i+1);
+ } else if ((*msg & 0xf0) == 0x20) {
+ printk ("-%x",msg[1]);
+ return (2);
+ };
+ return (1);
+}
+
+
+void ncr_int_sir (ncb_p np)
+{
+ u_char scntl3;
+ u_char chg, ofs, per, fak, wide;
+ u_char num = INB (nc_dsps);
+ ccb_p cp=0;
+ u_long dsa = INL (nc_dsa);
+ u_char target = INB (nc_sdid) & 0x0f;
+ tcb_p tp = &np->target[target];
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num);
+
+ switch (num) {
+ case SIR_SEL_ATN_NO_MSG_OUT:
+ /*
+ ** The device didn't go to MSG OUT phase after having
+ ** been selected with ATN. We donnot want to handle
+ ** that.
+ */
+ printk ("%s:%d: No MSG OUT phase after selection with ATN.\n",
+ ncr_name (np), target);
+ goto out_stuck;
+ case SIR_RESEL_NO_MSG_IN:
+ case SIR_RESEL_NO_IDENTIFY:
+ /*
+ ** If devices reselecting without sending an IDENTIFY
+ ** message still exist, this should help.
+ ** We just assume lun=0, 1 CCB, no tag.
+ */
+ if (tp->lp[0]) {
+ OUTL (nc_dsa, scr_to_cpu(tp->lp[0]->tasktbl[0]));
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, resel_go));
+ return;
+ }
+ case SIR_RESEL_BAD_LUN:
+ np->msgout[0] = M_RESET;
+ goto out;
+ case SIR_RESEL_BAD_I_T_L:
+ np->msgout[0] = M_ABORT;
+ goto out;
+ case SIR_RESEL_BAD_I_T_L_Q:
+ np->msgout[0] = M_ABORT_TAG;
+ goto out;
+ case SIR_RESEL_ABORTED:
+ np->lastmsg = np->msgout[0];
+ np->msgout[0] = M_NOOP;
+ printk ("%s:%d: message %d sent on bad reselection.\n",
+ ncr_name (np), target, np->lastmsg);
+ goto out;
+ case SIR_MSG_OUT_DONE:
+ np->lastmsg = np->msgout[0];
+ np->msgout[0] = M_NOOP;
+ /* Should we really care of that */
+ if (np->lastmsg == M_PARITY || np->lastmsg == M_ID_ERROR)
+ OUTOFFB (HF_PRT, HF_PAR_ERR);
+ goto out;
+ case SIR_BAD_STATUS:
+ cp = ncr_ccb_from_dsa(np, dsa);
+ if (!cp)
+ goto out;
+ ncr_sir_to_redo(np, num, cp);
+ return;
+ default:
+ /*
+ ** lookup the ccb
+ */
+ cp = ncr_ccb_from_dsa(np, dsa);
+ if (!cp)
+ goto out;
+ }
+
+ switch (num) {
+/*-----------------------------------------------------------------------------
+**
+** Was Sie schon immer ueber transfermode negotiation wissen wollten ...
+**
+** We try to negotiate sync and wide transfer only after
+** a successfull inquire command. We look at byte 7 of the
+** inquire data to determine the capabilities of the target.
+**
+** When we try to negotiate, we append the negotiation message
+** to the identify and (maybe) simple tag message.
+** The host status field is set to HS_NEGOTIATE to mark this
+** situation.
+**
+** If the target doesn't answer this message immidiately
+** (as required by the standard), the SIR_NEGO_FAIL interrupt
+** will be raised eventually.
+** The handler removes the HS_NEGOTIATE status, and sets the
+** negotiated value to the default (async / nowide).
+**
+** If we receive a matching answer immediately, we check it
+** for validity, and set the values.
+**
+** If we receive a Reject message immediately, we assume the
+** negotiation has failed, and fall back to standard values.
+**
+** If we receive a negotiation message while not in HS_NEGOTIATE
+** state, it's a target initiated negotiation. We prepare a
+** (hopefully) valid answer, set our parameters, and send back
+** this answer to the target.
+**
+** If the target doesn't fetch the answer (no message out phase),
+** we assume the negotiation has failed, and fall back to default
+** settings.
+**
+** When we set the values, we adjust them in all ccbs belonging
+** to this target, in the controller's register, and in the "phys"
+** field of the controller's struct ncb.
+**
+** Possible cases: hs sir msg_in value send goto
+** We try to negotiate:
+** -> target doesnt't msgin NEG FAIL noop defa. - dispatch
+** -> target rejected our msg NEG FAIL reject defa. - dispatch
+** -> target answered (ok) NEG SYNC sdtr set - clrack
+** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad
+** -> target answered (ok) NEG WIDE wdtr set - clrack
+** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad
+** -> any other msgin NEG FAIL noop defa. - dispatch
+**
+** Target tries to negotiate:
+** -> incoming message --- SYNC sdtr set SDTR -
+** -> incoming message --- WIDE wdtr set WDTR -
+** We sent our answer:
+** -> target doesn't msgout --- PROTO ? defa. - dispatch
+**
+**-----------------------------------------------------------------------------
+*/
+
+ case SIR_NEGO_FAILED:
+ /*-------------------------------------------------------
+ **
+ ** Negotiation failed.
+ ** Target doesn't send an answer message,
+ ** or target rejected our message.
+ **
+ ** Remove negotiation request.
+ **
+ **-------------------------------------------------------
+ */
+ OUTB (HS_PRT, HS_BUSY);
+
+ /* fall through */
+
+ case SIR_NEGO_PROTO:
+ /*-------------------------------------------------------
+ **
+ ** Negotiation failed.
+ ** Target doesn't fetch the answer message.
+ **
+ **-------------------------------------------------------
+ */
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("negotiation failed sir=%x status=%x.\n",
+ num, cp->nego_status);
+ };
+
+ /*
+ ** any error in negotiation:
+ ** fall back to default mode.
+ */
+ switch (cp->nego_status) {
+
+ case NS_SYNC:
+ ncr_setsync (np, cp, 0, 0xe0);
+ break;
+
+ case NS_WIDE:
+ ncr_setwide (np, cp, 0, 0);
+ break;
+
+ };
+ np->msgin [0] = M_NOOP;
+ np->msgout[0] = M_NOOP;
+ cp->nego_status = 0;
+ break;
+
+ case SIR_NEGO_SYNC:
+ /*
+ ** Synchronous request message received.
+ */
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync msgin: ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ };
+
+ /*
+ ** get requested values.
+ */
+
+ chg = 0;
+ per = np->msgin[3];
+ ofs = np->msgin[4];
+ if (ofs==0) per=255;
+
+ /*
+ ** if target sends SDTR message,
+ ** it CAN transfer synch.
+ */
+
+ if (ofs)
+ tp->inq_byte7 |= INQ7_SYNC;
+
+ /*
+ ** check values against driver limits.
+ */
+
+ if (per < np->minsync)
+ {chg = 1; per = np->minsync;}
+ if (per < tp->minsync)
+ {chg = 1; per = tp->minsync;}
+ if (ofs > tp->maxoffs)
+ {chg = 1; ofs = tp->maxoffs;}
+
+ /*
+ ** Check against controller limits.
+ */
+ fak = 7;
+ scntl3 = 0;
+ if (ofs != 0) {
+ ncr_getsync(np, per, &fak, &scntl3);
+ if (fak > 7) {
+ chg = 1;
+ ofs = 0;
+ }
+ }
+ if (ofs == 0) {
+ fak = 7;
+ per = 0;
+ scntl3 = 0;
+ tp->minsync = 0;
+ }
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n",
+ per, scntl3, ofs, fak, chg);
+ }
+
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ switch (cp->nego_status) {
+
+ case NS_SYNC:
+ /*
+ ** This was an answer message
+ */
+ if (chg) {
+ /*
+ ** Answer wasn't acceptable.
+ */
+ ncr_setsync (np, cp, 0, 0xe0);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
+ } else {
+ /*
+ ** Answer is ok.
+ */
+ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
+ };
+ return;
+
+ case NS_WIDE:
+ ncr_setwide (np, cp, 0, 0);
+ break;
+ };
+ };
+
+ /*
+ ** It was a request. Set value and
+ ** prepare an answer message
+ */
+
+ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
+
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 3;
+ np->msgout[2] = M_X_SYNC_REQ;
+ np->msgout[3] = per;
+ np->msgout[4] = ofs;
+
+ cp->nego_status = NS_SYNC;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync msgout: ");
+ (void) ncr_show_msg (np->msgout);
+ printk (".\n");
+ }
+
+ if (!ofs) {
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
+ return;
+ }
+ np->msgin [0] = M_NOOP;
+
+ break;
+
+ case SIR_NEGO_WIDE:
+ /*
+ ** Wide request message received.
+ */
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide msgin: ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ };
+
+ /*
+ ** get requested values.
+ */
+
+ chg = 0;
+ wide = np->msgin[3];
+
+ /*
+ ** if target sends WDTR message,
+ ** it CAN transfer wide.
+ */
+
+ if (wide)
+ tp->inq_byte7 |= INQ7_WIDE16;
+
+ /*
+ ** check values against driver limits.
+ */
+
+ if (wide > tp->usrwide)
+ {chg = 1; wide = tp->usrwide;}
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide: wide=%d chg=%d.\n", wide, chg);
+ }
+
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ switch (cp->nego_status) {
+
+ case NS_WIDE:
+ /*
+ ** This was an answer message
+ */
+ if (chg) {
+ /*
+ ** Answer wasn't acceptable.
+ */
+ ncr_setwide (np, cp, 0, 1);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
+ } else {
+ /*
+ ** Answer is ok.
+ */
+ ncr_setwide (np, cp, wide, 1);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
+ };
+ return;
+
+ case NS_SYNC:
+ ncr_setsync (np, cp, 0, 0xe0);
+ break;
+ };
+ };
+
+ /*
+ ** It was a request, set value and
+ ** prepare an answer message
+ */
+
+ ncr_setwide (np, cp, wide, 1);
+
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 2;
+ np->msgout[2] = M_X_WIDE_REQ;
+ np->msgout[3] = wide;
+
+ np->msgin [0] = M_NOOP;
+
+ cp->nego_status = NS_WIDE;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide msgout: ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ }
+ break;
+
+/*--------------------------------------------------------------------
+**
+** Processing of special messages
+**
+**--------------------------------------------------------------------
+*/
+
+ case SIR_REJECT_RECEIVED:
+ /*-----------------------------------------------
+ **
+ ** We received a M_REJECT message.
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_REJECT received (%x:%x).\n",
+ (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
+ break;
+
+ case SIR_REJECT_TO_SEND:
+ /*-----------------------------------------------
+ **
+ ** We received an unknown message
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_REJECT to send for ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ np->msgout[0] = M_REJECT;
+ break;
+
+/*--------------------------------------------------------------------
+**
+** Processing of special messages
+**
+**--------------------------------------------------------------------
+*/
+
+ case SIR_IGN_RESIDUE:
+ /*-----------------------------------------------
+ **
+ ** We received an IGNORE RESIDUE message,
+ ** which couldn't be handled by the script.
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_IGN_RESIDUE received, but not yet implemented.\n");
+ break;
+#if 0
+ case SIR_MISSING_SAVE:
+ /*-----------------------------------------------
+ **
+ ** We received an DISCONNECT message,
+ ** but the datapointer wasn't saved before.
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_DISCONNECT received, but datapointer not saved: "
+ "data=%x save=%x goal=%x.\n",
+ (unsigned) INL (nc_temp),
+ (unsigned) scr_to_cpu(np->header.savep),
+ (unsigned) scr_to_cpu(np->header.goalp));
+ break;
+#endif
+ };
+
+out:
+ OUTONB (nc_dcntl, (STD|NOCOM));
+out_stuck:


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

+** Aquire a control block


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

+static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln)

+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+ u_char tag = NO_TAG;
+ XPT_QUEHEAD *qp;
+ ccb_p cp = (ccb_p) 0;
+
+ /*
+ ** Allocate a new CCB if needed.
+ */
+ if (xpt_que_empty(&np->free_ccbq))
+ (void) ncr_alloc_ccb(np);
+
+ /*
+ ** Look for a free CCB
+ */
+ qp = xpt_remque_head(&np->free_ccbq);
+ if (!qp)
+ goto out;
+ cp = xpt_que_entry(qp, struct ccb, link_ccbq);
+
+ /*
+ ** If the LCB is not yet available and we already
+ ** have queued a CCB for a LUN without LCB,
+ ** give up. Otherwise all is fine. :-)
+ */
+ if (!lp) {
+ if (xpt_que_empty(&np->b0_ccbq))
+ xpt_insque_head(&cp->link_ccbq, &np->b0_ccbq);
+ else
+ goto out_free;
+ } else {
+ /*
+ ** Tune tag mode if asked by user.
+ */
+ if (lp->queuedepth != lp->numtags) {
+ ncr_setup_tags(np, tn, ln);
+ }
+
+ /*
+ ** Get a tag for this nexus if required.
+ ** Keep from using more tags than we can handle.
+ */
+ if (lp->usetags) {
+ if (lp->busyccbs < lp->maxnxs) {
+ tag = lp->cb_tags[lp->ia_tag];
+ ++lp->ia_tag;
+ if (lp->ia_tag == SCSI_NCR_MAX_TAGS)
+ lp->ia_tag = 0;
+ lp->tags_umap |= (((tagmap_t) 1) << tag);
+ }
+ else
+ goto out_free;
+ }
+
+ /*
+ ** Put the CCB in the LUN wait queue and
+ ** count it as busy.
+ */
+ xpt_insque_tail(&cp->link_ccbq, &lp->wait_ccbq);
+ ++lp->busyccbs;
+ }
+
+ /*
+ ** Remember all informations needed to free this CCB.
+ */
+ cp->tag = tag;
+ cp->target = tn;
+ cp->lun = ln;
+
+ if (DEBUG_FLAGS & DEBUG_TAGS) {
+ PRINT_LUN(np, tn, ln);
+ printk ("ccb @%p using tag %d.\n", cp, tag);
+ }
+
+out:
+ return cp;
+out_free:
+ xpt_insque_head(&cp->link_ccbq, &np->free_ccbq);
+ return (ccb_p) 0;


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

+** Release one control block


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

+static void ncr_free_ccb (ncb_p np, ccb_p cp)

+{
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = tp->lp[cp->lun];
+
+ if (DEBUG_FLAGS & DEBUG_TAGS) {
+ PRINT_LUN(np, cp->target, cp->lun);
+ printk ("ccb @%p freeing tag %d.\n", cp, cp->tag);
+ }
+
+ /*
+ ** If lun control block available, make available
+ ** the task slot and the tag if any.
+ ** Decrement counters.
+ */
+ if (lp) {
+ if (cp->tag != NO_TAG) {
+ lp->cb_tags[lp->if_tag++] = cp->tag;
+ if (lp->if_tag == SCSI_NCR_MAX_TAGS)
+ lp->if_tag = 0;
+ lp->tags_umap &= ~(((tagmap_t) 1) << cp->tag);
+ lp->tags_smap &= lp->tags_umap;
+ lp->tasktbl[cp->tag] = cpu_to_scr(np->p_bad_i_t_l_q);
+ } else {
+ lp->tasktbl[0] = cpu_to_scr(np->p_bad_i_t_l);
+ }
+ --lp->busyccbs;
+ if (cp->queued) {
+ --lp->queuedccbs;
+ }
+ }
+
+ /*
+ ** Make this CCB available.
+ */
+ xpt_remque(&cp->link_ccbq);
+ xpt_insque_head(&cp->link_ccbq, &np->free_ccbq);
+ cp -> host_status = HS_IDLE;
+ cp -> queued = 0;
+}
+
+/*------------------------------------------------------------------------
+** Allocate a CCB and initialize its fixed part.
+**------------------------------------------------------------------------
+**------------------------------------------------------------------------
+*/
+static ccb_p ncr_alloc_ccb(ncb_p np)
+{
+ ccb_p cp = 0;
+ int hcode;
+
+ /*
+ ** Allocate memory for this CCB.
+ */
+ cp = m_calloc(sizeof(struct ccb), "CCB", MEMO_WARN);
+ if (!cp)
+ return 0;
+
+ /*
+ ** Count it and initialyze it.
+ */
+ np->actccbs++;
+
+ /*
+ ** Remember virtual and bus address of this ccb.
+ */
+ cp->p_ccb = vtobus(cp);
+
+ /*
+ ** Insert this ccb into the hashed list.
+ */
+ hcode = CCB_HASH_CODE(cp->p_ccb);
+ cp->link_ccbh = np->ccbh[hcode];
+ np->ccbh[hcode] = cp;
+
+ /*
+ ** Initialyze the start and restart actions.
+ */
+ cp->phys.header.go.start = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ cp->phys.header.go.restart = cpu_to_scr(NCB_SCRIPTH_PHYS(np,bad_i_t_l));
+
+ /*
+ ** Chain into wakeup list and free ccb queue.
+ */
+ cp->link_ccb = np->ccbc;
+ np->ccbc = cp;
+
+ xpt_insque_head(&cp->link_ccbq, &np->free_ccbq);
+
+ return cp;
+}
+
+/*------------------------------------------------------------------------
+** Look up a CCB from a DSA value.
+**------------------------------------------------------------------------
+**------------------------------------------------------------------------
+*/


+static ccb_p ncr_ccb_from_dsa(ncb_p np, u_long dsa)

+{
+ int hcode;
+ ccb_p cp;
+
+ hcode = CCB_HASH_CODE(dsa);
+ cp = np->ccbh[hcode];
+ while (cp) {
+ if (cp->p_ccb == dsa)
+ break;
+ cp = cp->link_ccbh;
+ }
+
+ return cp;


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

+** Allocation of resources for Targets/Luns/Tags.


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

+/*------------------------------------------------------------------------
+** Target control block initialisation.
+**------------------------------------------------------------------------
+** This data structure is fully initialized after a SCSI command
+** has been successfully completed for this target.
+**------------------------------------------------------------------------
+*/


+static void ncr_init_tcb (ncb_p np, u_char tn)

+{
+ tcb_p tp = &np->target[tn];
+
+ /*
+ ** Already bone.
+ */
+ if (tp->luntbl)
+ return;
+ /*
+ ** Allocate the lcb bus address array.
+ */
+ tp->luntbl = m_calloc(256, "LUNTBL", MEMO_WARN);
+ if (!tp->luntbl)
+ return;
+
+ /*
+ ** Compute the bus address of this table.
+ */
+ tp->b_luntbl = cpu_to_scr(vtobus(tp->luntbl));
+
+ /*
+ ** Check some alignments required by the chip.
+ */
+ assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
+ offsetof(struct tcb , sval )) &3) == 0);
+ assert (( (offsetof(struct ncr_reg, nc_scntl3) ^
+ offsetof(struct tcb , wval )) &3) == 0);
+}
+
+/*------------------------------------------------------------------------
+** Lun control block allocation and initialization.
+**------------------------------------------------------------------------
+** This data structure is allocated and initialized after a SCSI
+** command has been successfully completed for this target/lun.
+**------------------------------------------------------------------------
+*/


+static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln)

+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+
+ /*
+ ** Already done, return.
+ */
+ if (lp)
+ return lp;
+
+ /*
+ ** Initialize the target control block if not yet.
+ */
+ ncr_init_tcb(np, tn);
+ if (!tp->luntbl)
+ goto fail;
+
+ /*
+ ** Allocate the lcb.
+ */
+ lp = m_calloc(sizeof(struct lcb), "LCB", MEMO_WARN);
+ if (!lp)
+ goto fail;
+ tp->lp[ln] = lp;
+
+ /*
+ ** Make it available to the chip.
+ */
+ tp->luntbl[ln] = cpu_to_scr(vtobus(lp));
+
+ /*
+ ** Initialize the CCB queue headers.
+ */
+ xpt_que_init(&lp->busy_ccbq);
+ xpt_que_init(&lp->wait_ccbq);
+
+ /*
+ ** Set max CCBs to 1 and use the default task array
+ ** by default.
+ */
+ lp->maxnxs = 1;
+ lp->tasktbl = &lp->tasktbl_0;
+ lp->b_tasktbl = cpu_to_scr(vtobus(lp->tasktbl));
+ lp->tasktbl[0] = cpu_to_scr(np->p_notask);
+ lp->resel_task = cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_notag));
+
+ /*
+ ** Initialize command queuing control.
+ */
+ lp->busyccbs = 1;
+ lp->queuedccbs = 1;
+ lp->queuedepth = 1;
+fail:
+ return lp;
+}
+
+
+/*------------------------------------------------------------------------
+** Lun control block setup on INQUIRY data received.
+**------------------------------------------------------------------------
+** We only support WIDE, SYNC for targets and CMDQ for logical units.
+** This setup is done on each INQUIRY since we are expecting user
+** will play with CHANGE DEFINITION commands. :-)
+**------------------------------------------------------------------------
+*/
+static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+ u_char inq_byte7;
+ int i;
+
+ /*
+ ** If no lcb, try to allocate it.
+ */
+ if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln)))
+ goto fail;
+
+ /*
+ ** Get device quirks from a speciality table.
+ */
+ tp->quirks = ncr_lookup (inq_data);
+ if (tp->quirks && bootverbose) {
+ PRINT_LUN(np, tn, ln);
+ printk ("quirks=%x.\n", tp->quirks);
+ }
+
+ /*
+ ** Evaluate trustable target/unit capabilities.
+ ** We only believe device version >= SCSI-2 that
+ ** use appropriate response data format (2).
+ ** But it seems that some CCS devices also
+ ** support SYNC and I donnot want to frustrate
+ ** anybody. ;-)
+ */
+ inq_byte7 = 0;
+ if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
+ inq_byte7 = inq_data[7];
+ else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1)
+ inq_byte7 = INQ7_SYNC;
+
+ /*
+ ** Throw away announced LUN capabilities if we are told
+ ** that there is no real device supported by the logical unit.
+ */
+ if ((inq_data[0] & 0xe0) > 0x20 || (inq_data[0] & 0x1f) == 0x1f)
+ inq_byte7 &= (INQ7_SYNC | INQ7_WIDE16);
+
+ /*
+ ** If user is wanting SYNC, force this feature.
+ */
+ if (driver_setup.force_sync_nego)
+ inq_byte7 |= INQ7_SYNC;
+
+ /*
+ ** Prepare negotiation if SIP capabilities have changed.
+ */
+ tp->inq_done = 1;
+ if ((inq_byte7 ^ tp->inq_byte7) & (INQ7_SYNC | INQ7_WIDE16)) {
+ tp->inq_byte7 = inq_byte7;
+ ncr_negotiate(np, tp);
+ }
+
+ /*
+ ** If unit supports tagged commands, allocate and
+ ** initialyze the task table if not yet.
+ */
+ if ((inq_byte7 & INQ7_QUEUE) && lp->tasktbl == &lp->tasktbl_0) {
+ lp->tasktbl = m_calloc(256, "TASKTBL", MEMO_WARN);
+ if (!lp->tasktbl) {
+ lp->tasktbl = &lp->tasktbl_0;
+ goto fail;
+ }
+ lp->b_tasktbl = cpu_to_scr(vtobus(lp->tasktbl));
+ for (i = 0 ; i < 64 ; i++)
+ lp->tasktbl[i] = cpu_to_scr(np->p_notask);
+ for (i = 0 ; i < SCSI_NCR_MAX_TAGS ; i++)
+ lp->cb_tags[i] = i;
+ lp->maxnxs = SCSI_NCR_MAX_TAGS;
+ lp->tags_stime = jiffies;
+ }
+
+ /*
+ ** Adjust tagged queueing status if needed.
+ */
+ if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) {
+ lp->inq_byte7 = inq_byte7;
+ lp->numtags = lp->maxtags;
+ ncr_setup_tags (np, tn, ln);
+ }
+
+fail:
+ return lp;


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

+** Build Scatter Gather Block
+**
+**
+**==========================================================
+**
+** The transfer area may be scattered among
+** several non adjacent physical pages.
+**
+** We may use MAX_SCATTER blocks.


+**
+**----------------------------------------------------------
+*/
+
+/*

+** We try to reduce the number of interrupts caused
+** by unexpected phase changes due to disconnects.
+** A typical harddisk may disconnect before ANY block.
+** If we wanted to avoid unexpected phase changes at all
+** we had to use a break point every 512 bytes.
+** Of course the number of scatter/gather blocks is
+** limited.
+** Under Linux, the scatter/gatter blocks are provided by
+** the generic driver. We just have to copy addresses and
+** sizes to the data segment array.
+*/
+
+/*
+** For 64 bit systems, we use the 8 upper bits of the size field
+** to provide bus address bits 32-39 to the SCRIPTS processor.
+** This allows the 896 to access up to 1 tera-bytes of memory.
+** For 32 bit chips on 64 bit systems, we must be provided with
+** memory addresses that fit into the first 32 bit bus address
+** range and so, this does not matter and we expect an error from
+** the chip if this ever happen.
+**
+** We use a separate function for the case Linux does not provide
+** a scatter list in order to allow better code optimization
+** for the case we have a scatter list (BTW, for now this just wastes
+** about 40 bytes of code for x86, but my guess is that the scatter
+** code will get more complex later).
+*/
+
+#if BITS_PER_LONG > 32
+#define SCATTER_ONE(data, badd, len) \
+ (data)->addr = cpu_to_scr(badd); \
+ (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len);


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 20'
echo 'File patch-2.2.6 is continued in part 21'
echo 21 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part23

#!/bin/sh
# this is part 23 of a 34 - part archive


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

if test "$Scheck" != 23; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

@@ -935,6 +935,7 @@
X if (dmap->audio_callback != NULL)
X dmap->audio_callback(dev, dmap->callback_parm);
X wake_up(&adev->out_sleeper);
+ wake_up(&adev->poll_sleeper);
X }
X
X static void do_outputintr(int dev, int dummy)
@@ -1103,7 +1104,10 @@
X }
X dmap->flags |= DMA_ACTIVE;
X if (dmap->qlen > 0)
+ {
X wake_up(&adev->in_sleeper);
+ wake_up(&adev->poll_sleeper);
+ }
X }
X
X void DMAbuf_inputintr(int dev)
@@ -1217,7 +1221,6 @@
X if (!(adev->open_mode & OPEN_READ))
X return 0;
X if (dmap->mapping_flags & DMA_MAP_MAPPED) {
- poll_wait(file, &adev->in_sleeper, wait);
X if (dmap->qlen)
X return POLLIN | POLLRDNORM;
X return 0;
@@ -1228,7 +1231,6 @@
X !dmap->qlen && adev->go) {


X unsigned long flags;
X

- poll_wait(file, &adev->in_sleeper, wait);
X save_flags(flags);
X cli();
X DMAbuf_activate_recording(dev, dmap);
@@ -1236,7 +1238,6 @@
X }
X return 0;
X }
- poll_wait(file, &adev->in_sleeper, wait);
X if (!dmap->qlen)
X return 0;
X return POLLIN | POLLRDNORM;
@@ -1250,14 +1251,12 @@
X if (!(adev->open_mode & OPEN_WRITE))
X return 0;
X if (dmap->mapping_flags & DMA_MAP_MAPPED) {
- poll_wait(file, &adev->out_sleeper, wait);
X if (dmap->qlen)
X return POLLOUT | POLLWRNORM;
X return 0;
X }
X if (dmap->dma_mode == DMODE_INPUT)
X return 0;
- poll_wait(file, &adev->out_sleeper, wait);
X if (dmap->dma_mode == DMODE_NONE)
X return POLLOUT | POLLWRNORM;
X if (!DMAbuf_space_in_queue(dev))
@@ -1267,6 +1266,8 @@
X
X unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait)
X {
+ struct audio_operations *adev = audio_devs[dev];
+ poll_wait(file, &adev->poll_sleeper, wait);
X return poll_input(file, dev, wait) | poll_output(file, dev, wait);
X }
X
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.2.5/linux/drivers/sound/es1370.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/sound/es1370.c Mon Apr 12 16:18:27 1999
@@ -3,7 +3,7 @@
X /*
X * es1370.c -- Ensoniq ES1370/Asahi Kasei AK4531 audio driver.
X *
- * Copyright (C) 1998 Thomas Sailer (sai...@ife.ee.ethz.ch)
+ * Copyright (C) 1998-1999 Thomas Sailer (sai...@ife.ee.ethz.ch)
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
@@ -87,6 +87,11 @@
X * reported by Johan Maes <jo...@telindus.be>
X * 22.03.99 0.19 return EAGAIN instead of EBUSY when O_NONBLOCK
X * read/write cannot be executed
+ * 07.04.99 0.20 implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ * Alpha fixes reported by Peter Jones <pjo...@redhat.com>
+ * Note: joystick address handling might still be wrong on archs
+ * other than i386
X *
X * some important things missing in Ensoniq documentation:
X *
@@ -287,7 +292,8 @@
X int dev_midi;
X
X /* hardware resources */
- unsigned int io, irq;
+ unsigned long io; /* long for SPARC */
+ unsigned int irq;
X
X /* mixer registers; there is no HW readback */
X struct {
@@ -1526,11 +1532,19 @@
X s->dma_dac2.subdivision = val;
X return 0;
X
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_RATE:
+ return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg);
+
X case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ?
+ 2 : 1, (int *)arg);
+
X case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ?
+ 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_FILTER:
X return -EINVAL;
X
@@ -1903,11 +1917,17 @@
X s->dma_dac1.subdivision = val;
X return 0;
X
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_RATE:
+ return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg);
+
X case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg);
+
X case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_FILTER:
X return -EINVAL;
X
@@ -2275,7 +2295,7 @@
X
X if (!pci_present()) /* No PCI bus in this machine! */
X return -ENODEV;
- printk(KERN_INFO "es1370: version v0.19 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.20 time " __TIME__ " " __DATE__ "\n");
X while (index < NR_DEVICE &&
X (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
X if (pcidev->base_address[0] == 0 ||
@@ -2299,7 +2319,7 @@
X s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
X s->irq = pcidev->irq;
X if (check_region(s->io, ES1370_EXTENT)) {
- printk(KERN_ERR "es1370: io ports %#x-%#x in use\n", s->io, s->io+ES1370_EXTENT-1);
+ printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
X goto err_region;
X }
X request_region(s->io, ES1370_EXTENT, "es1370");
@@ -2320,7 +2340,7 @@
X if (micz[index])
X s->ctrl |= CTRL_XCTL1;
X s->sctrl = 0;
- printk(KERN_INFO "es1370: found adapter at io %#06x irq %u\n"
+ printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
X KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
X s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
X (s->ctrl & CTRL_XCTL0) ? "out" : "in",
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.2.5/linux/drivers/sound/es1371.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/sound/es1371.c Mon Apr 12 16:18:27 1999
@@ -58,6 +58,13 @@
X * reported by Johan Maes <jo...@telindus.be>
X * 22.03.99 0.10 return EAGAIN instead of EBUSY when O_NONBLOCK
X * read/write cannot be executed
+ * 07.04.99 0.11 implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ * Alpha fixes reported by Peter Jones <pjo...@redhat.com>
+ * Another Alpha fix (wait_src_ready in init routine)
+ * reported by "Ivan N. Kokshaysky" <i...@jurassic.park.msu.ru>
+ * Note: joystick address handling might still be wrong on archs
+ * other than i386


X *
X */
X

@@ -334,7 +341,8 @@
X int dev_midi;
X
X /* hardware resources */
- unsigned int io, irq;
+ unsigned long io; /* long for SPARC */
+ unsigned int irq;
X
X /* mixer registers; there is no HW readback */
X struct {
@@ -1968,11 +1976,17 @@
X s->dma_dac2.subdivision = val;
X return 0;
X
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_RATE:
+ return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
+
X case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, (int *)arg);
+
X case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_FILTER:
X return -EINVAL;
X
@@ -2338,11 +2352,17 @@
X s->dma_dac1.subdivision = val;
X return 0;
X
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_RATE:
+ return put_user(s->dac1rate, (int *)arg);
+
X case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg);
+
X case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_FILTER:
X return -EINVAL;
X
@@ -2712,7 +2732,7 @@
X
X if (!pci_present()) /* No PCI bus in this machine! */
X return -ENODEV;
- printk(KERN_INFO "es1371: version v0.10 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1371: version v0.11 time " __TIME__ " " __DATE__ "\n");
X while (index < NR_DEVICE &&
X (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
X if (pcidev->base_address[0] == 0 ||
@@ -2736,7 +2756,7 @@
X s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
X s->irq = pcidev->irq;
X if (check_region(s->io, ES1371_EXTENT)) {
- printk(KERN_ERR "es1371: io ports %#x-%#x in use\n", s->io, s->io+ES1371_EXTENT-1);
+ printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
X goto err_region;
X }
X request_region(s->io, ES1371_EXTENT, "es1371");
@@ -2744,7 +2764,7 @@
X printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
X goto err_irq;
X }
- printk(KERN_INFO "es1371: found adapter at io %#06x irq %u\n"
+ printk(KERN_INFO "es1371: found adapter at io %#lx irq %u\n"
X KERN_INFO "es1371: features: joystick 0x%x\n", s->io, s->irq, joystick[index]);
X /* register devices */
X if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
@@ -2796,6 +2816,7 @@
X * be stuck high, and I've found no way to rectify this other than
X * power cycle)
X */
+ wait_src_ready(s);
X outl(0, s->io+ES1371_REG_SRCONV);
X /* codec init */
X wrcodec(s, 0x00, 0); /* reset codec */
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v2.2.5/linux/drivers/sound/sb.h Wed Mar 10 15:29:47 1999
+++ linux/drivers/sound/sb.h Mon Apr 12 16:18:27 1999
@@ -48,6 +48,7 @@
X #define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */
X #define MDL_AEDSP 15 /* Audio Excel DSP 16 */
X #define MDL_ESSPCI 16 /* ESS PCI card */
+#define MDL_YMPCI 17 /* Yamaha PCI sb in emulation */
X
X #define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */
X /* register assignment */
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.2.5/linux/drivers/sound/sb_card.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/sound/sb_card.c Mon Apr 12 16:18:27 1999
@@ -222,5 +222,8 @@
X EXPORT_SYMBOL(probe_sb);
X EXPORT_SYMBOL(unload_sb);
X EXPORT_SYMBOL(sb_be_quiet);
+EXPORT_SYMBOL(attach_sbmpu);
+EXPORT_SYMBOL(probe_sbmpu);
+EXPORT_SYMBOL(unload_sbmpu);
X
X #endif
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.2.5/linux/drivers/sound/sb_common.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/sound/sb_common.c Mon Apr 12 16:18:27 1999
@@ -261,7 +261,7 @@
X }
X }
X }
- DDB(printk("DSP version %d.%d\n", devc->major, devc->minor));
+ DDB(printk("DSP version %d.%02d\n", devc->major, devc->minor));
X restore_flags(flags);
X }
X
@@ -532,8 +532,12 @@
X
X if(pci == SB_PCI_YAMAHA)
X {
+ devc->model = MDL_YMPCI;
X devc->caps |= SB_PCI_IRQ;
X hw_config->driver_use_1 |= SB_PCI_IRQ;
+ hw_config->card_subtype = MDL_YMPCI;
+
+ printk("Yamaha PCI mode.\n");
X }
X
X if (acer)
@@ -600,6 +604,12 @@
X if(devc->type == MDL_ESSPCI)
X devc->model = MDL_ESSPCI;
X
+ if(devc->type == MDL_YMPCI)
+ {
+ printk("YMPCI selected\n");
+ devc->model = MDL_YMPCI;
+ }
+
X /*
X * Save device information for sb_dsp_init()
X */
@@ -612,7 +622,7 @@
X return 0;
X }
X memcpy((char *) detected_devc, (char *) devc, sizeof(sb_devc));
- MDB(printk(KERN_INFO "SB %d.%d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
+ MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));


X return 1;
X }
X

@@ -648,7 +658,7 @@
X
X devc->caps = hw_config->driver_use_1;
X
- if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0)
+ if (!((devc->caps & SB_NO_AUDIO) && (devc->caps & SB_NO_MIDI)) && hw_config->irq > 0)
X { /* IRQ setup */
X
X /*
@@ -807,7 +817,7 @@
X if (hw_config->name == NULL)
X hw_config->name = "Sound Blaster (8 BIT/MONO ONLY)";
X
- sprintf(name, "%s (%d.%d)", hw_config->name, devc->major, devc->minor);
+ sprintf(name, "%s (%d.%02d)", hw_config->name, devc->major, devc->minor);
X conf_printf(name, hw_config);
X
X /*
@@ -828,7 +838,7 @@
X }
X else if (!sb_be_quiet && devc->model == MDL_SBPRO)
X {
- printk(KERN_INFO "SB DSP version is just %d.%d which means that your card is\n", devc->major, devc->minor);
+ printk(KERN_INFO "SB DSP version is just %d.%02d which means that your card is\n", devc->major, devc->minor);
X printk(KERN_INFO "several years old (8 bit only device) or alternatively the sound driver\n");
X printk(KERN_INFO "is incorrectly configured.\n");
X }
@@ -1233,6 +1243,10 @@
X return 0;
X break;
X
+ case MDL_YMPCI:
+ hw_config->name = "Yamaha PCI Legacy";
+ printk("Yamaha PCI legacy UART401 check.\n");
+ break;
X default:
X return 0;
X }
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v2.2.5/linux/drivers/sound/sb_mixer.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/sound/sb_mixer.c Mon Apr 12 16:18:27 1999
@@ -674,6 +674,7 @@
X switch (devc->model)
X {
X case MDL_ESSPCI:
+ case MDL_YMPCI:
X case MDL_SBPRO:
X case MDL_AZTECH:
X case MDL_JAZZ:
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.2.5/linux/drivers/sound/sonicvibes.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/sound/sonicvibes.c Mon Apr 12 16:18:27 1999
@@ -3,7 +3,7 @@
X /*
X * sonicvibes.c -- S3 Sonic Vibes audio driver.
X *
- * Copyright (C) 1998 Thomas Sailer (sai...@ife.ee.ethz.ch)
+ * Copyright (C) 1998-1999 Thomas Sailer (sai...@ife.ee.ethz.ch)
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
@@ -55,6 +55,19 @@
X * reported by Johan Maes <jo...@telindus.be>
X * 22.03.99 0.12 return EAGAIN instead of EBUSY when O_NONBLOCK
X * read/write cannot be executed
+ * 05.04.99 0.13 added code to sv_read and sv_write which should detect
+ * lockups of the sound chip and revive it. This is basically
+ * an ugly hack, but at least applications using this driver
+ * won't hang forever. I don't know why these lockups happen,
+ * it might well be the motherboard chipset (an early 486 PCI
+ * board with ALI chipset), since every busmastering 100MB
+ * ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
+ * exhibit similar behaviour (they work for a couple of packets
+ * and then lock up and can be revived by ifconfig down/up).
+ * 07.04.99 0.14 implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ * Alpha fixes reported by Peter Jones <pjo...@redhat.com>
+ * Note: dmaio hack might still be wrong on archs other than i386


X *
X */
X

@@ -255,7 +268,8 @@
X int dev_dmfm;
X
X /* hardware resources */
- unsigned int iosb, ioenh, iosynth, iomidi, iogame, iodmaa, iodmac, irq;
+ unsigned long iosb, ioenh, iosynth, iomidi, iogame; /* long for SPARC */
+ unsigned int iodmaa, iodmac, irq;
X
X /* mixer stuff */
X struct {
@@ -1298,7 +1312,19 @@
X start_adc(s);
X if (file->f_flags & O_NONBLOCK)
X return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_adc.wait);
+ if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+ printk(KERN_DEBUG "sv: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,
+ s->dma_adc.hwptr, s->dma_adc.swptr);
+ stop_adc(s);
+ spin_lock_irqsave(&s->lock, flags);
+ set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.numfrag << s->dma_adc.fragshift);
+ /* program enhanced mode registers */
+ wrindir(s, SV_CIDMACBASECOUNT1, (s->dma_adc.fragsamples-1) >> 8);
+ wrindir(s, SV_CIDMACBASECOUNT0, s->dma_adc.fragsamples-1);
+ s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
X if (signal_pending(current))
X return ret ? ret : -ERESTARTSYS;
X continue;
@@ -1358,7 +1384,19 @@
X start_dac(s);
X if (file->f_flags & O_NONBLOCK)
X return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_dac.wait);
+ if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+ printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count,
+ s->dma_dac.hwptr, s->dma_dac.swptr);
+ stop_dac(s);
+ spin_lock_irqsave(&s->lock, flags);
+ set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.numfrag << s->dma_dac.fragshift);
+ /* program enhanced mode registers */
+ wrindir(s, SV_CIDMAABASECOUNT1, (s->dma_dac.fragsamples-1) >> 8);
+ wrindir(s, SV_CIDMAABASECOUNT0, s->dma_dac.fragsamples-1);
+ s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
X if (signal_pending(current))
X return ret ? ret : -ERESTARTSYS;
X continue;
@@ -1717,11 +1755,19 @@
X s->dma_dac.subdivision = val;
X return 0;
X
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_RATE:
+ return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+
X case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (SV_CFMT_STEREO << SV_CFMT_CSHIFT)
+ : (SV_CFMT_STEREO << SV_CFMT_ASHIFT))) ? 2 : 1, (int *)arg);
+
X case SOUND_PCM_READ_BITS:
+ return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (SV_CFMT_16BIT << SV_CFMT_CSHIFT)
+ : (SV_CFMT_16BIT << SV_CFMT_ASHIFT))) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
X case SOUND_PCM_READ_FILTER:
X return -EINVAL;
X
@@ -2275,7 +2321,7 @@
X
X if (!pci_present()) /* No PCI bus in this machine! */
X return -ENODEV;
- printk(KERN_INFO "sv: version v0.12 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.14 time " __TIME__ " " __DATE__ "\n");
X #if 0
X if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
X printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2329,7 +2375,7 @@
X }
X pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9); /* enable and use extended mode */
X pci_write_config_dword(pcidev, 0x48, s->iodmac | 9); /* enable */
- printk(KERN_DEBUG "sv: io ports: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#lx %#x %#x\n",
X s->iosb, s->ioenh, s->iosynth, s->iomidi, s->iogame, s->iodmaa, s->iodmac);
X if (s->ioenh == 0 || s->iodmaa == 0 || s->iodmac == 0)
X continue;
@@ -2339,7 +2385,7 @@
X pci_write_config_dword(pcidev, 0x60, wavetable_mem >> 12); /* wavetable base address */
X
X if (check_region(s->ioenh, SV_EXTENT_ENH)) {
- printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
+ printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
X goto err_region5;
X }
X request_region(s->ioenh, SV_EXTENT_ENH, "S3 SonicVibes PCM");
@@ -2354,12 +2400,12 @@
X }
X request_region(s->iodmac, SV_EXTENT_DMA, "S3 SonicVibes DMAC");
X if (check_region(s->iomidi, SV_EXTENT_MIDI)) {
- printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+SV_EXTENT_MIDI-1);
+ printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iomidi, s->iomidi+SV_EXTENT_MIDI-1);
X goto err_region2;
X }
X request_region(s->iomidi, SV_EXTENT_MIDI, "S3 SonicVibes Midi");
X if (check_region(s->iosynth, SV_EXTENT_SYNTH)) {
- printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
+ printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
X goto err_region1;
X }
X request_region(s->iosynth, SV_EXTENT_SYNTH, "S3 SonicVibes Synth");
@@ -2390,7 +2436,7 @@
X printk(KERN_ERR "sv: irq %u in use\n", s->irq);
X goto err_irq;
X }
- printk(KERN_INFO "sv: found adapter at io %#06x irq %u dmaa %#06x dmac %#06x revision %u\n",
+ printk(KERN_INFO "sv: found adapter at io %#lx irq %u dmaa %#06x dmac %#06x revision %u\n",
X s->ioenh, s->irq, s->iodmaa, s->iodmac, rdindir(s, SV_CIREVISION));
X /* register devices */
X if ((s->dev_audio = register_sound_dsp(&sv_audio_fops, -1)) < 0)
diff -u --recursive --new-file v2.2.5/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v2.2.5/linux/drivers/sound/sscape.c Sun Nov 8 14:03:04 1998
+++ linux/drivers/sound/sscape.c Mon Apr 12 16:18:27 1999
@@ -943,7 +943,9 @@
X
X mpu_config.irq = mpu_irq;
X mpu_config.io_base = mpu_io;
-
+ /* WEH - Try to get right dma channel */
+ mpu_config.dma = dma;
+
X if(spea != -1)
X {
X old_hardware = spea;
diff -u --recursive --new-file v2.2.5/linux/drivers/video/promcon.c linux/drivers/video/promcon.c
--- v2.2.5/linux/drivers/video/promcon.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/video/promcon.c Fri Apr 16 08:20:23 1999
@@ -5,6 +5,7 @@
X * Copyright (C) 1998 Jakub Jelinek (j...@ultra.linux.cz)
X */
X
+#include <linux/config.h>


X #include <linux/module.h>
X #include <linux/kernel.h>

X #include <linux/errno.h>
diff -u --recursive --new-file v2.2.5/linux/drivers/video/sgivwfb.c linux/drivers/video/sgivwfb.c
--- v2.2.5/linux/drivers/video/sgivwfb.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/video/sgivwfb.c Fri Apr 16 08:20:23 1999
@@ -9,6 +9,7 @@
X * more details.
X */
X
+#include <linux/config.h>


X #include <linux/module.h>
X #include <linux/kernel.h>

X #include <linux/errno.h>
diff -u --recursive --new-file v2.2.5/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.2.5/linux/drivers/video/vesafb.c Wed Mar 10 15:29:48 1999
+++ linux/drivers/video/vesafb.c Mon Apr 12 09:57:34 1999
@@ -93,6 +93,7 @@
X } fbcon_cmap;
X
X static int inverse = 0;
+static int mtrr = 0;
X static int currcon = 0;
X
X static int pmi_setpal = 0; /* pmi for palette changes ??? */
@@ -495,6 +496,8 @@
X pmi_setpal=0;
X else if (! strcmp(this_opt, "pmipal"))
X pmi_setpal=1;
+ else if (! strcmp(this_opt, "mtrr"))
+ mtrr=1;
X else if (!strncmp(this_opt, "font:", 5))
X strcpy(fb_info.fontname, this_opt+5);
X }
@@ -633,7 +636,8 @@
X }
X request_region(0x3c0, 32, "vga+");
X #ifdef CONFIG_MTRR
- mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
+ if (mtrr)
+ mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
X #endif
X
X strcpy(fb_info.modename, "VESA VGA");
diff -u --recursive --new-file v2.2.5/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.2.5/linux/fs/affs/namei.c Tue Dec 22 14:16:57 1998
+++ linux/fs/affs/namei.c Mon Apr 12 10:03:45 1999
@@ -548,32 +548,14 @@
X "No inode for entry found (key=%lu)\n",new_ino);
X goto end_rename;
X }
- if (new_inode == old_inode) {
- if (old_ino == new_ino) { /* Filename might have changed case */
- retval = new_dentry->d_name.len < 31 ? new_dentry->d_name.len : 30;
- strncpy(DIR_END(old_bh->b_data,old_inode)->dir_name + 1,
- new_dentry->d_name.name,retval);
- DIR_END(old_bh->b_data,old_inode)->dir_name[0] = retval;
- goto new_checksum;
- }
- retval = 0;
- goto end_rename;
- }
X if (S_ISDIR(old_inode->i_mode)) {
- retval = -EINVAL;
- if (is_subdir(new_dentry, old_dentry))
- goto end_rename;
X if (new_inode) {
- if (new_dentry->d_count > 1)
- shrink_dcache_parent(new_dentry);
- retval = -EBUSY;
- if (new_dentry->d_count > 1)
- goto end_rename;
X retval = -ENOTEMPTY;
X if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
X goto end_rename;
X }
X
+ retval = -ENOENT;
X if (affs_parent_ino(old_inode) != old_dir->i_ino)
X goto end_rename;
X }
@@ -593,7 +575,6 @@
X affs_copy_name(FILE_END(old_bh->b_data,old_inode)->file_name,new_dentry->d_name.name);
X if ((retval = affs_insert_hash(new_dir->i_ino,old_bh,new_dir)))
X goto end_rename;
-new_checksum:
X affs_fix_checksum(AFFS_I2BSIZE(new_dir),old_bh->b_data,5);
X
X new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime
@@ -604,7 +585,6 @@
X mark_inode_dirty(new_dir);
X mark_inode_dirty(old_dir);
X mark_buffer_dirty(old_bh,1);
- d_move(old_dentry,new_dentry);
X
X end_rename:
X affs_brelse(old_bh);
diff -u --recursive --new-file v2.2.5/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.2.5/linux/fs/coda/dir.c Mon Jan 25 17:44:34 1999
+++ linux/fs/coda/dir.c Mon Apr 12 10:03:45 1999
@@ -246,12 +246,6 @@
X
X dircnp = ITOC(dir);
X
- if ( length > CODA_MAXNAMLEN ) {
- printk("name too long: create, %s(%s)\n",
- coda_f2s(&dircnp->c_fid), name);
- return -ENAMETOOLONG;
- }
-
X error = venus_create(dir->i_sb, &(dircnp->c_fid), name, length,
X 0, mode, 0, &newfid, &attrs);
X
@@ -302,12 +296,6 @@
X
X dircnp = ITOC(dir);
X
- if ( length > CODA_MAXNAMLEN ) {
- printk("name too long: mknod, %s(%s)\n",
- coda_f2s(&dircnp->c_fid), name);
- return -ENAMETOOLONG;
- }
-
X error = venus_create(dir->i_sb, &(dircnp->c_fid), name, length,
X 0, mode, rdev, &newfid, &attrs);
X
@@ -349,9 +337,6 @@
X return -ENOENT;
X }
X
- if ( len > CODA_MAXNAMLEN )
- return -ENAMETOOLONG;
-
X if (coda_isroot(dir) && coda_iscontrol(name, len))
X return -EPERM;
X
@@ -409,11 +394,6 @@
X CDEBUG(D_INODE, "old: fid: %s\n", coda_f2s(&(cnp->c_fid)));
X CDEBUG(D_INODE, "directory: %s\n", coda_f2s(&(dir_cnp->c_fid)));
X
- if ( len > CODA_MAXNAMLEN ) {
- printk("coda_link: name too long. \n");
- return -ENAMETOOLONG;
- }
-
X error = venus_link(dir_inode->i_sb,&(cnp->c_fid), &(dir_cnp->c_fid),
X (const char *)name, len);
X
@@ -448,9 +428,6 @@
X if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
X return -EPERM;
X
- if ( len > CODA_MAXNAMLEN )
- return -ENAMETOOLONG;
-
X symlen = strlen(symname);
X if ( symlen > CODA_MAXPATHLEN )
X return -ENAMETOOLONG;
@@ -519,9 +496,6 @@
X }
X dircnp = ITOC(dir);
X
- if (len > CODA_MAXNAMLEN)
- return -ENAMETOOLONG;
-
X if (!list_empty(&de->d_hash))
X return -EBUSY;
X error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
@@ -545,7 +519,6 @@
X const char *new_name = new_dentry->d_name.name;
X int old_length = old_dentry->d_name.len;
X int new_length = new_dentry->d_name.len;
- struct inode *old_inode = old_dentry->d_inode;
X struct inode *new_inode = new_dentry->d_inode;
X struct coda_inode_info *new_cnp, *old_cnp;
X int error;
@@ -553,10 +526,6 @@
X ENTRY;
X coda_vfs_stat.rename++;
X
- if ( (old_length > CODA_MAXNAMLEN) || new_length > CODA_MAXNAMLEN ) {
- return -ENAMETOOLONG;
- }
-
X old_cnp = ITOC(old_dir);
X new_cnp = ITOC(new_dir);
X
@@ -565,21 +534,6 @@
X old_name, old_length, strlen(old_name), new_name, new_length,
X strlen(new_name),old_dentry->d_count, new_dentry->d_count);
X
- if (new_inode == old_inode)
- return 0;
-
- /* make sure target is not in use */
- if (new_inode && S_ISDIR(new_inode->i_mode)) {
- /*
- * Prune any children before testing for busy.
- */
- if (new_dentry->d_count > 1)
- shrink_dcache_parent(new_dentry);
-
- if (new_dentry->d_count > 1)
- return -EBUSY;
- }
-
X /* the C library will do unlink/create etc */
X if ( coda_crossvol_rename == 0 &&
X old_cnp->c_fid.Volume != new_cnp->c_fid.Volume )
@@ -599,7 +553,6 @@
X coda_flag_inode(new_dir, C_VATTR);
X
X CDEBUG(D_INODE, "result %d\n", error);
- d_move(old_dentry, new_dentry);
X
X EXIT;
X return 0;
@@ -637,7 +590,9 @@
X result = coda_venus_readdir(&open_file, dirent, filldir);
X } else {
X /* potemkin case: we are handed a directory inode */
+ down(&cnp->c_ovp->i_sem);
X result = open_file.f_op->readdir(&open_file, dirent, filldir);
+ up(&cnp->c_ovp->i_sem);
X }
X coda_restore_codafile(inode, file, cnp->c_ovp, &open_file);
X EXIT;
diff -u --recursive --new-file v2.2.5/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.2.5/linux/fs/ext2/namei.c Tue Dec 22 14:16:57 1998
+++ linux/fs/ext2/namei.c Mon Apr 12 10:03:45 1999
@@ -218,12 +218,6 @@
X return NULL;
X sb = dir->i_sb;
X
- if (namelen > EXT2_NAME_LEN)
- {
- *err = -ENAMETOOLONG;
- return NULL;
- }
-
X if (!namelen)
X return NULL;
X /*
@@ -409,10 +403,6 @@
X struct ext2_dir_entry_2 * de;
X int err = -EIO;
X
- err = -ENAMETOOLONG;
- if (dentry->d_name.len > EXT2_NAME_LEN)
- goto out;
-
X inode = ext2_new_inode (dir, mode, &err);
X if (!inode)
X goto out;
@@ -474,10 +464,6 @@
X struct ext2_dir_entry_2 * de;
X int err;
X
- err = -ENAMETOOLONG;
- if (dentry->d_name.len > EXT2_NAME_LEN)
- goto out;
-
X err = -EMLINK;
X if (dir->i_nlink >= EXT2_LINK_MAX)
X goto out;
@@ -618,10 +604,6 @@
X struct buffer_head * bh;
X struct ext2_dir_entry_2 * de;
X
- retval = -ENAMETOOLONG;
- if (dentry->d_name.len > EXT2_NAME_LEN)
- goto out;
-
X retval = -ENOENT;
X bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
X if (!bh)
@@ -634,14 +616,12 @@
X if (le32_to_cpu(de->inode) != inode->i_ino)
X goto end_rmdir;
X
+ retval = -ENOTEMPTY;
X if (!empty_dir (inode))
- retval = -ENOTEMPTY;
- else if (le32_to_cpu(de->inode) != inode->i_ino)
- retval = -ENOENT;
- else {
- retval = ext2_delete_entry (de, bh);
- dir->i_version = ++event;
- }
+ goto end_rmdir;
+
+ retval = ext2_delete_entry (de, bh);
+ dir->i_version = ++event;
X if (retval)
X goto end_rmdir;
X mark_buffer_dirty(bh, 1);
@@ -665,7 +645,6 @@
X
X end_rmdir:
X brelse (bh);
-out:


X return retval;
X }
X

@@ -676,10 +655,6 @@
X struct buffer_head * bh;
X struct ext2_dir_entry_2 * de;
X
- retval = -ENAMETOOLONG;
- if (dentry->d_name.len > EXT2_NAME_LEN)
- goto out;
-
X retval = -ENOENT;
X bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
X if (!bh)
@@ -718,7 +693,6 @@
X
X end_unlink:
X brelse (bh);
-out:


X return retval;
X }
X

@@ -805,9 +779,6 @@
X if (S_ISDIR(inode->i_mode))
X return -EPERM;
X
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return -EPERM;
-
X if (inode->i_nlink >= EXT2_LINK_MAX)
X return -EMLINK;
X
@@ -851,17 +822,10 @@
X le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode
X
X /*
- * rename uses retrying to avoid race-conditions: at least they should be
- * minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
X * Anybody can rename anything with this: the permission checks are left to the
X * higher-level routines.
X */
-static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
+int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
X struct inode * new_dir,struct dentry *new_dentry)
X {
X struct inode * old_inode, * new_inode;
@@ -870,9 +834,6 @@
X int retval;
X
X old_bh = new_bh = dir_bh = NULL;
- retval = -ENAMETOOLONG;
- if (old_dentry->d_name.len > EXT2_NAME_LEN)
- goto end_rename;
X
X old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
X /*
@@ -897,24 +858,13 @@
X DQUOT_INIT(new_inode);
X }
X }
- retval = 0;
- if (new_inode == old_inode)
- goto end_rename;
X if (S_ISDIR(old_inode->i_mode)) {
- retval = -EINVAL;
- if (is_subdir(new_dentry, old_dentry))
- goto end_rename;
X if (new_inode) {
- /* Prune any children before testing for busy */
- if (new_dentry->d_count > 1)
- shrink_dcache_parent(new_dentry);
- retval = -EBUSY;
- if (new_dentry->d_count > 1)
- goto end_rename;
X retval = -ENOTEMPTY;
X if (!empty_dir (new_inode))
X goto end_rename;
X }
+ retval = -EIO;
X dir_bh = ext2_bread (old_inode, 0, 0, &retval);
X if (!dir_bh)
X goto end_rename;
@@ -977,8 +927,6 @@
X wait_on_buffer (new_bh);
X }
X
- /* Update the dcache */
- d_move(old_dentry, new_dentry);
X retval = 0;
X
X end_rename:
@@ -986,31 +934,4 @@
X brelse (old_bh);
X brelse (new_bh);
X return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- *
- * In the second extended file system, we use a lock flag stored in the memory
- * super-block. This way, we really lock other renames only if they occur
- * on the same file system
- */
-int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
- struct inode * new_dir, struct dentry *new_dentry)
-{
- int result;
-
- while (old_dir->i_sb->u.ext2_sb.s_rename_lock)
- sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
- old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
- result = do_ext2_rename (old_dir, old_dentry, new_dir, new_dentry);
- old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
- wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
- return result;
X }
diff -u --recursive --new-file v2.2.5/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.2.5/linux/fs/ext2/super.c Tue Mar 23 14:35:48 1999
+++ linux/fs/ext2/super.c Mon Apr 12 10:03:45 1999
@@ -543,8 +543,6 @@
X else
X sb->u.ext2_sb.s_resgid = le16_to_cpu(es->s_def_resgid);
X sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
- sb->u.ext2_sb.s_rename_lock = 0;
- sb->u.ext2_sb.s_rename_wait = NULL;
X sb->u.ext2_sb.s_addr_per_block_bits =
X log2 (EXT2_ADDR_PER_BLOCK(sb));
X sb->u.ext2_sb.s_desc_per_block_bits =
diff -u --recursive --new-file v2.2.5/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.2.5/linux/fs/fat/inode.c Thu Jan 7 15:11:38 1999
+++ linux/fs/fat/inode.c Thu Apr 15 06:07:21 1999
@@ -3,6 +3,10 @@
X *
X * Written 1992,1993 by Werner Almesberger
X * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
+ *
+ * Fixes:
+ *
+ * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0


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

@@ -362,8 +366,16 @@
X fat32 = 1;
X MSDOS_SB(sb)->fat_length= CF_LE_W(b->fat32_length)*sector_mult;
X MSDOS_SB(sb)->root_cluster = CF_LE_L(b->root_cluster);
- MSDOS_SB(sb)->fsinfo_offset =
- CF_LE_W(b->info_sector) * logical_sector_size + 0x1e0;
+
+ /* MC - if info_sector is 0, don't multiply by 0 */
+ if(CF_LE_W(b->info_sector) == 0) {
+ MSDOS_SB(sb)->fsinfo_offset =
+ logical_sector_size + 0x1e0;
+ } else {
+ MSDOS_SB(sb)->fsinfo_offset =
+ (CF_LE_W(b->info_sector) * logical_sector_size)
+ + 0x1e0;
+ }
X if (MSDOS_SB(sb)->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) {
X printk("fat_read_super: Bad fsinfo_offset\n");
X fat_brelse(sb, bh);
diff -u --recursive --new-file v2.2.5/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.2.5/linux/fs/hfs/dir.c Tue Dec 22 14:16:57 1998
+++ linux/fs/hfs/dir.c Mon Apr 12 10:03:45 1999
@@ -430,8 +430,6 @@
X update_dirs_plus(new_parent, is_dir);
X }
X
- /* update dcache */
- d_move(old_dentry, new_dentry);
X }
X
X hfs_rename_put:
diff -u --recursive --new-file v2.2.5/linux/fs/inode.c linux/fs/inode.c
--- v2.2.5/linux/fs/inode.c Tue Mar 23 14:35:48 1999
+++ linux/fs/inode.c Thu Apr 15 05:42:49 1999
@@ -529,15 +529,6 @@
X }
X
X /*
- * This gets called with I_LOCK held: it needs
- * to read the inode and then unlock it
- */
-static inline void read_inode(struct inode *inode, struct super_block *sb)
-{
- sb->s_op->read_inode(inode);
-}
-
-/*
X * This is called by things like the networking layer
X * etc that want to get an inode without any inode
X * number, or filesystems that allocate new inodes with
@@ -606,7 +597,7 @@
X spin_unlock(&inode_lock);
X
X clean_inode(inode);
- read_inode(inode, sb);
+ sb->s_op->read_inode(inode);
X
X /*
X * This is special! We do not need the spinlock
diff -u --recursive --new-file v2.2.5/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.2.5/linux/fs/minix/inode.c Fri Nov 27 13:09:28 1998
+++ linux/fs/minix/inode.c Tue Apr 13 07:54:02 1999
@@ -195,8 +195,8 @@
X s->u.minix_sb.s_ms = ms;
X s->u.minix_sb.s_sbh = bh;
X s->u.minix_sb.s_mount_state = ms->s_state;
- s->s_blocksize = 1024;
- s->s_blocksize_bits = 10;
+ s->s_blocksize = BLOCK_SIZE;
+ s->s_blocksize_bits = BLOCK_SIZE_BITS;
X s->u.minix_sb.s_ninodes = ms->s_ninodes;
X s->u.minix_sb.s_nzones = ms->s_nzones;
X s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks;
diff -u --recursive --new-file v2.2.5/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.2.5/linux/fs/minix/namei.c Tue Dec 22 14:16:57 1998
+++ linux/fs/minix/namei.c Mon Apr 12 10:03:45 1999
@@ -604,7 +604,7 @@
X * Anybody can rename anything with this: the permission checks are left to the
X * higher-level routines.
X */
-static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry,
+int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
X struct inode * new_dir, struct dentry *new_dentry)
X {
X struct inode * old_inode, * new_inode;
@@ -640,24 +640,11 @@
X new_bh = NULL;
X }
X }
- if (new_inode == old_inode) {
- retval = 0;
- goto end_rename;
- }
X if (S_ISDIR(old_inode->i_mode)) {
- retval = -EINVAL;
- if (is_subdir(new_dentry, old_dentry))
- goto end_rename;
X if (new_inode) {
- /* Prune any children before testing for busy */
- if (new_dentry->d_count > 1)
- shrink_dcache_parent(new_dentry);
- retval = -EBUSY;
- if (new_dentry->d_count > 1)
X retval = -ENOTEMPTY;
X if (!empty_dir(new_inode))
X goto end_rename;
- retval = -EBUSY;
X }
X retval = -EIO;
X dir_bh = minix_bread(old_inode,0,0);
@@ -713,38 +700,10 @@
X mark_inode_dirty(new_dir);
X }
X }
- /* Update the dcache */
- d_move(old_dentry, new_dentry);
X retval = 0;
X end_rename:
X brelse(dir_bh);
X brelse(old_bh);
X brelse(new_bh);
X return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
-int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
- struct inode * new_dir, struct dentry *new_dentry)
-{
- static struct wait_queue * wait = NULL;
- static int lock = 0;
- int result;
-
- while (lock)
- sleep_on(&wait);
- lock = 1;
- result = do_minix_rename(old_dir, old_dentry,
- new_dir, new_dentry);
- lock = 0;
- wake_up(&wait);
- return result;
X }
diff -u --recursive --new-file v2.2.5/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.2.5/linux/fs/msdos/namei.c Tue Dec 22 14:16:57 1998
+++ linux/fs/msdos/namei.c Mon Apr 12 10:03:45 1999
@@ -327,6 +327,7 @@
X fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
X de->size = 0;
X fat_mark_buffer_dirty(sb, bh, 1);
+
X if ((*result = iget(dir->i_sb,ino)) != NULL)
X msdos_read_inode(*result);
X fat_brelse(sb, bh);
@@ -405,23 +406,22 @@
X struct msdos_dir_entry *de;
X int result = 0;
X
- if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
- pos = 0;
- bh = NULL;
- while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
- /* Ignore vfat longname entries */
- if (de->attr == ATTR_EXT)
- continue;
- if (!IS_FREE(de->name) &&
- strncmp(de->name,MSDOS_DOT , MSDOS_NAME) &&
- strncmp(de->name,MSDOS_DOTDOT, MSDOS_NAME)) {
- result = -ENOTEMPTY;
- break;
- }
+ pos = 0;
+ bh = NULL;
+ while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
+ /* Ignore vfat longname entries */
+ if (de->attr == ATTR_EXT)
+ continue;
+ if (!IS_FREE(de->name) &&
+ strncmp(de->name,MSDOS_DOT , MSDOS_NAME) &&
+ strncmp(de->name,MSDOS_DOTDOT, MSDOS_NAME)) {
+ result = -ENOTEMPTY;
+ break;
X }
- if (bh)
- fat_brelse(dir->i_sb, bh);
X }
+ if (bh)
+ fat_brelse(dir->i_sb, bh);
+
X return result;
X }
X
@@ -444,13 +444,8 @@
X * whether it is empty.
X */
X res = -EBUSY;
- if (!list_empty(&dentry->d_hash)) {
-#ifdef MSDOS_DEBUG
-printk("msdos_rmdir: %s/%s busy, d_count=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
-#endif
+ if (!list_empty(&dentry->d_hash))
X goto rmdir_done;
- }
X res = msdos_empty(inode);
X if (res)
X goto rmdir_done;
@@ -503,14 +498,6 @@
X dir->i_nlink++;
X inode->i_nlink = 2; /* no need to mark them dirty */
X
-#ifdef whatfor
- /*
- * He's dead, Jim. We don't d_instantiate anymore. Should do it
- * from the very beginning, actually.
- */
- MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
-#endif
-
X if ((res = fat_add_cluster(inode)) < 0)
X goto mkdir_error;
X if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0)
@@ -529,9 +516,6 @@
X MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
X dot->i_nlink = dir->i_nlink;
X mark_inode_dirty(dot);
-#ifdef whatfor
- MSDOS_I(inode)->i_busy = 0;
-#endif
X iput(dot);
X d_instantiate(dentry, inode);
X res = 0;
@@ -606,110 +590,9 @@
X return msdos_unlinkx (dir,dentry,0);
X }
X
-#define MSDOS_CHECK_BUSY 1
-
-/***** Rename within a directory */
-static int msdos_rename_same(struct inode *old_dir,char *old_name,
- struct dentry *old_dentry,
- struct inode *new_dir,char *new_name,struct dentry *new_dentry,
- struct buffer_head *old_bh,
- struct msdos_dir_entry *old_de, int old_ino, int is_hid)
-{
- struct super_block *sb = old_dir->i_sb;
- struct buffer_head *new_bh;
- struct msdos_dir_entry *new_de;
- struct inode *new_inode,*old_inode;
- int new_ino, exists, error;
-
- if (!strncmp(old_name, new_name, MSDOS_NAME))
- goto set_hid;
- error = -ENOENT;
- if (*(unsigned char *) old_de->name == DELETED_FLAG)
- goto out;
-
- exists = fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
- if (exists) {
- error = -EIO;
- new_inode = new_dentry->d_inode;
- /* Make sure it really exists ... */
- if (!new_inode) {
- printk(KERN_ERR
- "msdos_rename_same: %s/%s inode NULL, ino=%d\n",
- new_dentry->d_parent->d_name.name,
- new_dentry->d_name.name, new_ino);
- d_drop(new_dentry);
- goto out_error;
- }
- error = S_ISDIR(new_inode->i_mode)
- ? (old_de->attr & ATTR_DIR)
- ? msdos_empty(new_inode)
- : -EPERM
- : (old_de->attr & ATTR_DIR)
- ? -EPERM
- : 0;
- if (error)
- goto out_error;
- error = -EPERM;
- if ((old_de->attr & ATTR_SYS))
- goto out_error;
-
- if (S_ISDIR(new_inode->i_mode)) {
- /* make sure it's empty */
- error = msdos_empty(new_inode);
- if (error)
- goto out_error;
-#ifdef MSDOS_CHECK_BUSY
- /* check for a busy dentry */
- error = -EBUSY;
- shrink_dcache_parent(new_dentry);
- if (new_dentry->d_count > 1) {
-printk("msdos_rename_same: %s/%s busy, count=%d\n",
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-new_dentry->d_count);
- goto out_error;
- }
-#endif
- new_dir->i_nlink--;
- mark_inode_dirty(new_dir);
- }
- new_inode->i_nlink = 0;
- MSDOS_I(new_inode)->i_busy = 1;
- mark_inode_dirty(new_inode);
- /*
- * Make it negative if it's not busy;
- * otherwise let d_move() drop it.
- */
- if (new_dentry->d_count == 1)
- d_delete(new_dentry);
-
- new_de->name[0] = DELETED_FLAG;
- fat_mark_buffer_dirty(sb, new_bh, 1);
- fat_brelse(sb, new_bh);
- }
- memcpy(old_de->name, new_name, MSDOS_NAME);
- /* Update the dcache */
- d_move(old_dentry, new_dentry);
-set_hid:
- old_de->attr = is_hid
- ? (old_de->attr | ATTR_HIDDEN)
- : (old_de->attr &~ ATTR_HIDDEN);
- fat_mark_buffer_dirty(sb, old_bh, 1);
- /* update binary info for conversion, i_attrs */
- old_inode = old_dentry->d_inode;
- MSDOS_I(old_inode)->i_attrs = is_hid
- ? (MSDOS_I(old_inode)->i_attrs | ATTR_HIDDEN)
- : (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
- error = 0;
-out:
- return error;
-
-out_error:
- fat_brelse(sb, new_bh);
- goto out;
-}
-
+/* Now we could merge it with msdos_rename_same. Later */
X /***** Rename across directories - a nonphysical move */
-static int msdos_rename_diff(struct inode *old_dir, char *old_name,
+static int do_msdos_rename(struct inode *old_dir, char *old_name,
X struct dentry *old_dentry,
X struct inode *new_dir,char *new_name, struct dentry *new_dentry,
X struct buffer_head *old_bh,
@@ -718,30 +601,27 @@
X struct super_block *sb = old_dir->i_sb;
X struct buffer_head *new_bh,*free_bh,*dotdot_bh;
X struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
- struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode;
+ struct inode *old_inode,*new_inode,*dotdot_inode;
X int new_ino,free_ino,dotdot_ino;
X int error, exists;
X
- error = -EINVAL;
- if (old_ino == new_dir->i_ino)
- goto out;
- /* prevent moving directory below itself */
- if (is_subdir(new_dentry, old_dentry))
- goto out;
-
+ old_inode = old_dentry->d_inode;
+ if (old_dir==new_dir && !strncmp(old_name, new_name, MSDOS_NAME))
+ goto set_hid;
X error = -ENOENT;
X if (*(unsigned char *) old_de->name == DELETED_FLAG)
X goto out;
X
X /* find free spot */
- while ((error = fat_scan(new_dir, NULL, &free_bh, &free_de, &free_ino,
- SCAN_ANY)) < 0) {
- if (error != -ENOENT)
- goto out;
- error = fat_add_cluster(new_dir);
- if (error)
- goto out;
- }
+ if (new_dir!=old_dir)
+ while ((error = fat_scan(new_dir, NULL, &free_bh, &free_de,
+ &free_ino, SCAN_ANY)) < 0) {
+ if (error != -ENOENT)
+ goto out;
+ error = fat_add_cluster(new_dir);
+ if (error)
+ goto out;
+ }
X
X exists = fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
X if (exists) { /* Trash the old file! */
@@ -750,40 +630,17 @@
X /* Make sure it really exists ... */
X if (!new_inode) {
X printk(KERN_ERR
- "msdos_rename_diff: %s/%s inode NULL, ino=%d\n",
+ "msdos_rename: %s/%s inode NULL, ino=%d\n",
X new_dentry->d_parent->d_name.name,
X new_dentry->d_name.name, new_ino);
X d_drop(new_dentry);
X goto out_new;
X }
- error = S_ISDIR(new_inode->i_mode)
- ? (old_de->attr & ATTR_DIR)
- ? msdos_empty(new_inode)
- : -EPERM
- : (old_de->attr & ATTR_DIR)
- ? -EPERM
- : 0;
- if (error)
- goto out_new;
X error = -EPERM;
X if ((old_de->attr & ATTR_SYS))
X goto out_new;
X
-#ifdef MSDOS_CHECK_BUSY
- /* check for a busy dentry */
- error = -EBUSY;
- if (new_dentry->d_count > 1) {
- shrink_dcache_parent(new_dentry);
- if (new_dentry->d_count > 1) {
-printk("msdos_rename_diff: target %s/%s busy, count=%d\n",
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-new_dentry->d_count);
- goto out_new;
- }
- }
-#endif
X if (S_ISDIR(new_inode->i_mode)) {
- /* make sure it's empty */
X error = msdos_empty(new_inode);
X if (error)
X goto out_new;
@@ -793,18 +650,26 @@
X new_inode->i_nlink = 0;
X MSDOS_I(new_inode)->i_busy = 1;
X mark_inode_dirty(new_inode);
- /*
- * Make it negative if it's not busy;
- * otherwise let d_move() drop it.
- */
- if (new_dentry->d_count == 1)
- d_delete(new_dentry);
+
X new_de->name[0] = DELETED_FLAG;
X fat_mark_buffer_dirty(sb, new_bh, 1);
X fat_brelse(sb, new_bh);
X }
X
- old_inode = old_dentry->d_inode;
+ if (old_dir==new_dir) {
+ memcpy(old_de->name, new_name, MSDOS_NAME);
+set_hid:
+ old_de->attr = is_hid
+ ? (old_de->attr | ATTR_HIDDEN)
+ : (old_de->attr &~ ATTR_HIDDEN);
+ fat_mark_buffer_dirty(sb, old_bh, 1);
+ MSDOS_I(old_inode)->i_attrs = is_hid
+ ? (MSDOS_I(old_inode)->i_attrs | ATTR_HIDDEN)
+ : (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
+ error = 0;


+ goto out;
+ }
+

X /* Get the dotdot inode if we'll need it ... */
X dotdot_bh = NULL;
X dotdot_inode = NULL;
@@ -824,73 +689,37 @@
X goto out_dotdot;
X }
X
- /* get an inode for the new name */
+ /*
+ * Potential race here. It will go away when we'll switch to
+ * sane inumbers (along with a frigging lot of other races).
+ */
+
+ /* set new entry */
X memcpy(free_de, old_de, sizeof(struct msdos_dir_entry));
X memcpy(free_de->name, new_name, MSDOS_NAME);
X free_de->attr = is_hid
X ? (free_de->attr|ATTR_HIDDEN)
X : (free_de->attr&~ATTR_HIDDEN);
X
- error = -EIO;
- free_inode = iget(sb, free_ino);
- if (!free_inode)
- goto out_iput;
- /* make sure it's not busy! */
- if (MSDOS_I(free_inode)->i_busy)
- printk(KERN_ERR "msdos_rename_diff: new inode %ld busy!\n",
- (ino_t) free_ino);
- if (!list_empty(&free_inode->i_dentry))
- printk("msdos_rename_diff: free inode has aliases??\n");
- msdos_read_inode(free_inode);
-
X /*
- * Make sure the old dentry isn't busy,
- * as we need to change inodes ...
+ * Now the tricky part. We need to change i_ino. icache ignores
+ * i_ino for unhashed inodes, so we'll remove inode from hash,
+ * change what we want to change and reinsert it back. NB: we
+ * don't have to invalidate FAT cache here - all we need is to
+ * flip i_ino in relevant cache entries. Later.
X */
- error = -EBUSY;
- if (old_dentry->d_count > 1) {
- shrink_dcache_parent(old_dentry);
- if (old_dentry->d_count > 1) {
-printk("msdos_rename_diff: source %s/%s busy, count=%d\n",
-old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
-old_dentry->d_count);
- goto out_iput;
- }
- }
-
- /* keep the inode for a bit ... */
- old_inode->i_count++;
- d_delete(old_dentry);
-
- free_inode->i_mode = old_inode->i_mode;
- free_inode->i_nlink = old_inode->i_nlink;
- free_inode->i_size = old_inode->i_size;
- free_inode->i_blocks = old_inode->i_blocks;
- free_inode->i_mtime = old_inode->i_mtime;
- free_inode->i_atime = old_inode->i_atime;
- free_inode->i_ctime = old_inode->i_ctime;
- MSDOS_I(free_inode)->i_ctime_ms = MSDOS_I(old_inode)->i_ctime_ms;
-
- MSDOS_I(free_inode)->i_start = MSDOS_I(old_inode)->i_start;
- MSDOS_I(free_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
- MSDOS_I(free_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
-
- /* release the old inode's resources */
- MSDOS_I(old_inode)->i_start = 0;
- MSDOS_I(old_inode)->i_logstart = 0;
- old_inode->i_nlink = 0;
-
- /*
- * Install the new inode ...
- */
- d_instantiate(old_dentry, free_inode);
+ remove_inode_hash(old_inode);
X
- fat_mark_buffer_dirty(sb, free_bh, 1);
X fat_cache_inval_inode(old_inode);
- mark_inode_dirty(old_inode);
+ old_inode->i_version = ++event;
+ MSDOS_I(old_inode)->i_binary =
+ is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext);
+ old_inode->i_ino = free_ino;
+ fat_mark_buffer_dirty(sb, free_bh, 1);
X old_de->name[0] = DELETED_FLAG;
X fat_mark_buffer_dirty(sb, old_bh, 1);
- iput(old_inode);
+
+ insert_inode_hash(old_inode);
X
X /* a directory? */
X if (dotdot_bh) {
@@ -908,8 +737,6 @@
X fat_brelse(sb, dotdot_bh);
X }
X
- /* Update the dcache */
- d_move(old_dentry, new_dentry);
X error = 0;
X
X rename_done:
@@ -917,14 +744,6 @@
X out:
X return error;
X
-out_iput:
- free_de->name[0] = DELETED_FLAG;
- /*
- * Don't mark free_bh as dirty. Both states
- * are supposed to be equivalent.
- */
- iput(free_inode); /* may be NULL */
- iput(dotdot_inode);
X out_dotdot:
X fat_brelse(sb, dotdot_bh);
X goto rename_done;
@@ -944,9 +763,6 @@
X int is_hid,old_hid; /* if new file and old file are hidden */
X char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
X
- error = -EINVAL;
- if (sb != new_dir->i_sb)
- goto rename_done;
X error = msdos_format_name(MSDOS_SB(sb)->options.name_check,
X old_dentry->d_name.name, old_dentry->d_name.len,
X old_msdos_name, 1,MSDOS_SB(sb)->options.dotsOK);
@@ -966,14 +782,9 @@
X goto rename_done;
X
X fat_lock_creation();
- if (old_dir == new_dir)
- error = msdos_rename_same(old_dir, old_msdos_name, old_dentry,
- new_dir, new_msdos_name, new_dentry,
- old_bh, old_de, (ino_t)old_ino, is_hid);
- else
- error = msdos_rename_diff(old_dir, old_msdos_name, old_dentry,
- new_dir, new_msdos_name, new_dentry,
- old_bh, old_de, (ino_t)old_ino, is_hid);
+ error = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
+ new_dir, new_msdos_name, new_dentry,
+ old_bh, old_de, (ino_t)old_ino, is_hid);
X fat_unlock_creation();
X fat_brelse(sb, old_bh);
X
diff -u --recursive --new-file v2.2.5/linux/fs/namei.c linux/fs/namei.c
--- v2.2.5/linux/fs/namei.c Mon Jan 25 17:44:34 1999
+++ linux/fs/namei.c Thu Apr 15 06:11:56 1999
@@ -279,7 +279,8 @@
X {
X struct inode * inode = dentry->d_inode;
X
- if (inode && inode->i_op && inode->i_op->follow_link) {
+ if ((follow & LOOKUP_FOLLOW)
+ && inode && inode->i_op && inode->i_op->follow_link) {
X if (current->link_count < 5) {
X struct dentry * result;
X
@@ -403,9 +404,6 @@
X /* Check mountpoints.. */
X dentry = follow_mount(dentry);
X
- if (!(flags & LOOKUP_FOLLOW))
- break;
-
X base = do_follow_link(base, dentry, flags);
X if (IS_ERR(base))
X goto return_base;
@@ -1034,17 +1032,13 @@
X int error;
X
X error = may_delete(dir, dentry, 0);
- if (error)
- goto exit_lock;
-
- if (!dir->i_op || !dir->i_op->unlink)
- goto exit_lock;
-
- DQUOT_INIT(dir);
-
- error = dir->i_op->unlink(dir, dentry);
-
-exit_lock:
+ if (!error) {
+ error = -EPERM;
+ if (dir->i_op && dir->i_op->unlink) {
+ DQUOT_INIT(dir);
+ error = dir->i_op->unlink(dir, dentry);
+ }
+ }
X return error;
X }
X
@@ -1231,15 +1225,16 @@
X return error;
X }
X
-int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
X struct inode *new_dir, struct dentry *new_dentry)
X {
X int error;
- int isdir;
+ int need_rehash = 0;
X
- isdir = S_ISDIR(old_dentry->d_inode->i_mode);
+ if (old_dentry->d_inode == new_dentry->d_inode)
+ return 0;
X
- error = may_delete(old_dir, old_dentry, isdir); /* XXX */
+ error = may_delete(old_dir, old_dentry, 1);
X if (error)
X return error;
X
@@ -1249,18 +1244,89 @@
X if (!new_dentry->d_inode)
X error = may_create(new_dir, new_dentry);
X else
- error = may_delete(new_dir, new_dentry, isdir);
+ error = may_delete(new_dir, new_dentry, 1);
X if (error)
X return error;
X
X if (!old_dir->i_op || !old_dir->i_op->rename)
X return -EPERM;
X
+ /*
+ * If we are going to change the parent - check write permissions,
+ * we'll need to flip '..'.
+ */
+ if (new_dir != old_dir) {
+ error = permission(old_dentry->d_inode, MAY_WRITE);
+ }
+ if (error)
+ return error;
+
X DQUOT_INIT(old_dir);
X DQUOT_INIT(new_dir);
+ down(&old_dir->i_sb->s_vfs_rename_sem);
+ error = -EINVAL;
+ if (is_subdir(new_dentry, old_dentry))
+ goto out_unlock;
+ if (new_dentry->d_inode) {
+ error = -EBUSY;
+ if (d_invalidate(new_dentry)<0)
+ goto out_unlock;
+ need_rehash = 1;
+ }
X error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-
+ if (need_rehash)
+ d_rehash(new_dentry);
+ if (!error)
+ d_move(old_dentry,new_dentry);
+out_unlock:
+ up(&old_dir->i_sb->s_vfs_rename_sem);
X return error;
+}
+
+int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ int error;
+
+ if (old_dentry->d_inode == new_dentry->d_inode)
+ return 0;
+
+ error = may_delete(old_dir, old_dentry, 0);
+ if (error)
+ return error;
+
+ if (new_dir->i_dev != old_dir->i_dev)
+ return -EXDEV;
+
+ if (!new_dentry->d_inode)
+ error = may_create(new_dir, new_dentry);
+ else
+ error = may_delete(new_dir, new_dentry, 0);
+ if (error)
+ return error;
+
+ if (!old_dir->i_op || !old_dir->i_op->rename)
+ return -EPERM;
+
+ DQUOT_INIT(old_dir);
+ DQUOT_INIT(new_dir);
+ error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+ if (error)
+ return error;
+ /* The following d_move() should become unconditional */
+ if (!(old_dir->i_sb->s_flags & MS_ODD_RENAME)) {
+ d_move(old_dentry, new_dentry);
+ }


+ return 0;
+}
+

+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ if (S_ISDIR(old_dentry->d_inode->i_mode))
+ return vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
+ else
+ return vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
X }
X
X static inline int do_rename(const char * oldname, const char * newname)
diff -u --recursive --new-file v2.2.5/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.2.5/linux/fs/ncpfs/dir.c Wed Dec 16 10:32:55 1998
+++ linux/fs/ncpfs/dir.c Mon Apr 12 10:03:45 1999
@@ -303,6 +303,8 @@
X
X memset(&ia,0,sizeof(struct iattr));


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 23'
echo 'File patch-2.2.6 is continued in part 24'
echo 24 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part24

#!/bin/sh
# this is part 24 of a 34 - part archive


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

if test "$Scheck" != 24; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

X ia.ia_mode = old_dentry->d_inode->i_mode;
+ if (S_ISDIR(ia.ia_mode))
+ goto leave_me;
X ia.ia_mode |= NCP_SERVER(old_dir)->m.file_mode & 0222; /* set write bits */
X ia.ia_valid = ATTR_MODE;
X
@@ -1125,7 +1127,8 @@
X old_dentry->d_name.name,new_dentry->d_name.name);
X ncp_invalid_dir_cache(old_dir);
X ncp_invalid_dir_cache(new_dir);
- d_move(old_dentry,new_dentry);
+ if (!S_ISDIR(old_dentry->d_inode->i_mode))
+ d_move(old_dentry,new_dentry);
X }
X } else {
X if (error == 0x9E)
diff -u --recursive --new-file v2.2.5/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.2.5/linux/fs/ncpfs/inode.c Tue Mar 23 14:35:48 1999
+++ linux/fs/ncpfs/inode.c Mon Apr 12 10:03:45 1999
@@ -264,6 +264,8 @@
X
X lock_super(sb);
X
+ sb->s_flags |= MS_ODD_RENAME; /* This should go away */
+
X sb->s_blocksize = 1024; /* Eh... Is this correct? */
X sb->s_blocksize_bits = 10;
X sb->s_magic = NCP_SUPER_MAGIC;
diff -u --recursive --new-file v2.2.5/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.2.5/linux/fs/nfs/dir.c Wed Mar 10 15:29:49 1999
+++ linux/fs/nfs/dir.c Mon Apr 12 10:03:45 1999
@@ -624,10 +624,6 @@
X dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
X dir->i_dev, dir->i_ino, dentry->d_name.name);
X
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X sattr.mode = mode;
X sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
X sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
@@ -642,7 +638,6 @@
X error = nfs_instantiate(dentry, &fhandle, &fattr);
X if (error)
X d_drop(dentry);
-out:


X return error;
X }
X

@@ -659,9 +654,6 @@
X dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
X dir->i_dev, dir->i_ino, dentry->d_name.name);
X
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- return -ENAMETOOLONG;
-
X sattr.mode = mode;
X sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
X if (S_ISCHR(mode) || S_ISBLK(mode))
@@ -691,10 +683,6 @@
X dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
X dir->i_dev, dir->i_ino, dentry->d_name.name);
X
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X sattr.mode = mode | S_IFDIR;
X sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
X sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
@@ -709,7 +697,6 @@
X nfs_invalidate_dircache(dir);
X error = nfs_proc_mkdir(NFS_DSERVER(dentry), NFS_FH(dentry->d_parent),
X dentry->d_name.name, &sattr, &fhandle, &fattr);
-out:


X return error;
X }
X

@@ -720,10 +707,6 @@
X dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
X dir->i_dev, dir->i_ino, dentry->d_name.name);
X
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X #ifdef NFS_PARANOIA
X if (dentry->d_inode->i_count > 1)
X printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
@@ -742,7 +725,6 @@
X dentry->d_inode->i_nlink --;
X }
X
-out:


X return error;
X }
X

@@ -952,10 +934,6 @@
X dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n",
X dir->i_dev, dir->i_ino, dentry->d_name.name);
X
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X error = nfs_sillyrename(dir, dentry);
X if (error && error != -EBUSY) {
X error = nfs_safe_remove(dentry);
@@ -963,7 +941,6 @@
X nfs_renew_times(dentry);
X }
X }
-out:


X return error;
X }
X

@@ -977,9 +954,6 @@
X dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
X
X error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X if (strlen(symname) > NFS_MAXPATHLEN)
X goto out;
X
@@ -1026,10 +1000,6 @@
X old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
X dentry->d_parent->d_name.name, dentry->d_name.name);
X
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X /*
X * Drop the dentry in advance to force a new lookup.
X * Since nfs_proc_link doesn't return a file handle,
@@ -1046,7 +1016,6 @@
X */
X inode->i_nlink++;
X }
-out:


X return error;
X }
X

@@ -1087,11 +1056,6 @@
X new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
X new_dentry->d_count);
X
- error = -ENAMETOOLONG;
- if (old_dentry->d_name.len > NFS_MAXNAMLEN ||
- new_dentry->d_name.len > NFS_MAXNAMLEN)
- goto out;
-
X /*
X * First check whether the target is busy ... we can't
X * safely do _any_ rename if the target is in use.
@@ -1100,28 +1064,24 @@
X * silly-rename. If the silly-rename succeeds, the
X * copied dentry is hashed and becomes the new target.
X *
- * For directories, prune any unused children.
+ * With directories check is done in VFS.
X */
X error = -EBUSY;
X if (new_dentry->d_count > 1 && new_inode) {
- if (S_ISREG(new_inode->i_mode)) {
- int err;
- /* copy the target dentry's name */
- dentry = d_alloc(new_dentry->d_parent,
- &new_dentry->d_name);
- if (!dentry)
- goto out;
-
- /* silly-rename the existing target ... */
- err = nfs_sillyrename(new_dir, new_dentry);
- if (!err) {
- new_dentry = dentry;
- new_inode = NULL;
- /* hash the replacement target */
- d_add(new_dentry, NULL);
- }
- } else if (!list_empty(&new_dentry->d_subdirs)) {
- shrink_dcache_parent(new_dentry);
+ int err;
+ /* copy the target dentry's name */
+ dentry = d_alloc(new_dentry->d_parent,
+ &new_dentry->d_name);
+ if (!dentry)
+ goto out;
+
+ /* silly-rename the existing target ... */
+ err = nfs_sillyrename(new_dir, new_dentry);
+ if (!err) {
+ new_dentry = dentry;
+ new_inode = NULL;
+ /* hash the replacement target */
+ d_add(new_dentry, NULL);
X }
X
X /* dentry still busy? */
@@ -1196,7 +1156,7 @@
X error = nfs_proc_rename(NFS_DSERVER(old_dentry),
X NFS_FH(old_dentry->d_parent), old_dentry->d_name.name,
X NFS_FH(new_dentry->d_parent), new_dentry->d_name.name);
- if (!error) {
+ if (!error && !S_ISDIR(old_inode->i_mode)) {
X /* Update the dcache if needed */
X if (rehash)
X d_add(new_dentry, NULL);
diff -u --recursive --new-file v2.2.5/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.2.5/linux/fs/nfs/inode.c Wed Mar 10 15:29:49 1999
+++ linux/fs/nfs/inode.c Mon Apr 12 10:03:45 1999
@@ -224,6 +224,8 @@
X
X lock_super(sb);
X
+ sb->s_flags |= MS_ODD_RENAME; /* This should go away */
+
X sb->s_magic = NFS_SUPER_MAGIC;
X sb->s_op = &nfs_sops;
X sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
diff -u --recursive --new-file v2.2.5/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v2.2.5/linux/fs/nfs/symlink.c Mon Sep 28 10:51:35 1998
+++ linux/fs/nfs/symlink.c Mon Apr 12 09:57:11 1999
@@ -54,13 +54,12 @@
X dfprintk(VFS, "nfs: readlink(%s/%s)\n",
X dentry->d_parent->d_name.name, dentry->d_name.name);
X
- if (buflen > NFS_MAXPATHLEN)
- buflen = NFS_MAXPATHLEN;
X error = nfs_proc_readlink(NFS_DSERVER(dentry), NFS_FH(dentry),
- &mem, &res, &len, buflen);
+ &mem, &res, &len, NFS_MAXPATHLEN);
X if (! error) {
+ if (len > buflen)
+ len = buflen;
X copy_to_user(buffer, res, len);
- put_user('\0', buffer + len);
X error = len;
X kfree(mem);
X }
diff -u --recursive --new-file v2.2.5/linux/fs/nfsd/nfs3proc.c linux/fs/nfsd/nfs3proc.c
--- v2.2.5/linux/fs/nfsd/nfs3proc.c Mon Sep 1 12:26:04 1997
+++ linux/fs/nfsd/nfs3proc.c Mon Apr 12 10:07:36 1999
@@ -339,8 +339,10 @@
X nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
X argp->tname, argp->tlen,
X &newfh);
- if (nfserr)
+ if (!nfserr) {
+ argp->attrs.ia_valid &= ~ATTR_SIZE;
X nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs);
+ }
X
X fh_put(&argp->ffh);
X fh_put(&newfh);
@@ -362,6 +364,7 @@
X SVCFH_INO(&argp->fh),
X argp->name);
X
+ argp->attrs.ia_valid &= ~ATTR_SIZE;
X nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
X &argp->attrs, S_IFDIR, 0, &resp->fh);
X fh_put(&argp->fh);
diff -u --recursive --new-file v2.2.5/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.2.5/linux/fs/nfsd/nfsproc.c Tue Feb 23 15:21:34 1999
+++ linux/fs/nfsd/nfsproc.c Mon Apr 12 10:08:18 1999
@@ -382,8 +382,10 @@
X nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
X argp->tname, argp->tlen,
X &newfh);
- if (!nfserr)
+ if (!nfserr) {
+ argp->attrs.ia_valid &= ~ATTR_SIZE;
X nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs);
+ }
X
X fh_put(&argp->ffh);
X fh_put(&newfh);
@@ -407,6 +409,7 @@
X "nfsd_proc_mkdir: response already verified??\n");
X }
X
+ argp->attrs.ia_valid &= ~ATTR_SIZE;
X nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
X &argp->attrs, S_IFDIR, 0, &resp->fh);
X fh_put(&argp->fh);
diff -u --recursive --new-file v2.2.5/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.2.5/linux/fs/nfsd/vfs.c Tue Mar 23 14:35:48 1999
+++ linux/fs/nfsd/vfs.c Mon Apr 12 10:03:45 1999
@@ -959,7 +959,7 @@
X goto out_unlock;
X
X err = nfserr_perm;
- if (IS_IMMUTABLE(dest) /* || IS_APPEND(dest) */ )
+ if (IS_IMMUTABLE(dest) || IS_APPEND(dest))
X goto out_unlock;
X if (!dirp->i_op || !dirp->i_op->link)
X goto out_unlock;
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/Makefile linux/fs/ntfs/Makefile
--- v2.2.5/linux/fs/ntfs/Makefile Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/Makefile Mon Apr 12 10:05:58 1999
@@ -3,7 +3,7 @@
X O_TARGET := ntfs.o
X O_OBJS := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o
X M_OBJS := $(O_TARGET)
-EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"990102\"
+EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"990411\"
X
X include $(TOPDIR)/Rules.make
X
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c
--- v2.2.5/linux/fs/ntfs/attr.c Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/attr.c Mon Apr 12 10:05:58 1999
@@ -1,9 +1,10 @@
X /*
X * attr.c
X *
- * Copyright (C) 1996-1998 Martin von Löwis
+ * Copyright (C) 1996-1999 Martin von Löwis
X * Copyright (C) 1996-1997 Régis Duchesne
X * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Steve Dodd
X */
X
X #include "ntfstypes.h"
@@ -11,6 +12,9 @@
X #include "attr.h"
X
X #include <linux/errno.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
X #include "macros.h"
X #include "support.h"
X #include "util.h"
@@ -18,8 +22,9 @@
X #include "inode.h"
X
X /* Look if an attribute already exists in the inode, and if not, create it */
-static int
-new_attr(ntfs_inode *ino,int type,void *name,int namelen,int *pos, int *found)
+int
+ntfs_new_attr(ntfs_inode *ino,int type,void *name,int namelen,int *pos,
+ int *found, int do_search )
X {
X int do_insert=0;
X int i;
@@ -28,15 +33,17 @@
X {
X int n=min(namelen,ino->attrs[i].namelen);
X int s=ntfs_uni_strncmp(ino->attrs[i].name,name,n);
- /*
- * We assume that each attribute can be uniquely
- * identified by inode
- * number, attribute type and attribute name.
- */
- if(ino->attrs[i].type==type && ino->attrs[i].namelen==namelen && !s){
- *found=1;
- *pos=i;
- return 0;
+ if( do_search ) {
+ /*
+ * We assume that each attribute can be uniquely
+ * identified by inode
+ * number, attribute type and attribute name.
+ */
+ if(ino->attrs[i].type==type && ino->attrs[i].namelen==namelen && !s){
+ *found=1;
+ *pos=i;


+ return 0;
+ }
X }

X /* attributes are ordered by type, then by name */
X if(ino->attrs[i].type>type || (ino->attrs[i].type==type && s==1)){
@@ -48,17 +55,21 @@
X /* re-allocate space */
X if(ino->attr_count % 8 ==0)
X {
- ntfs_attribute* old=ino->attrs;
- ino->attrs = (ntfs_attribute*)ntfs_malloc((ino->attr_count+8)*
+ ntfs_attribute* new;
+ new = (ntfs_attribute*)ntfs_malloc((ino->attr_count+8)*
X sizeof(ntfs_attribute));
- if(old){
- ntfs_memcpy(ino->attrs,old,ino->attr_count*sizeof(ntfs_attribute));
- ntfs_free(old);
+ if( !new )
+ return ENOMEM;
+ if( ino->attrs ) {
+ ntfs_memcpy( new, ino->attrs, ino->attr_count*sizeof(ntfs_attribute) );
+ ntfs_free( ino->attrs );
X }
+ ino->attrs = new;
X }
X if(do_insert)
X ntfs_memmove(ino->attrs+i+1,ino->attrs+i,(ino->attr_count-i)*
X sizeof(ntfs_attribute));
+
X ino->attr_count++;
X ino->attrs[i].type=type;
X ino->attrs[i].namelen=namelen;
@@ -81,19 +92,21 @@
X }
X
X /* Store in the inode readable information about a run */
-static void
+void
X ntfs_insert_run(ntfs_attribute *attr,int cnum,ntfs_cluster_t cluster,int len)
X {
X /* (re-)allocate space if necessary */
X if(attr->d.r.len % 8 == 0) {
- ntfs_runlist* old;
- old=attr->d.r.runlist;
- attr->d.r.runlist=ntfs_malloc((attr->d.r.len+8)*sizeof(ntfs_runlist));
- if(old) {
- ntfs_memcpy(attr->d.r.runlist,old,attr->d.r.len
+ ntfs_runlist* new;
+ new = ntfs_malloc((attr->d.r.len+8)*sizeof(ntfs_runlist));
+ if( !new )
+ return;
+ if( attr->d.r.runlist ) {
+ ntfs_memcpy(new, attr->d.r.runlist, attr->d.r.len
X *sizeof(ntfs_runlist));
- ntfs_free(old);
+ ntfs_free( attr->d.r.runlist );
X }
+ attr->d.r.runlist = new;
X }
X if(attr->d.r.len>cnum)
X ntfs_memmove(attr->d.r.runlist+cnum+1,attr->d.r.runlist+cnum,
@@ -103,6 +116,13 @@
X attr->d.r.len++;
X }
X
+/* Extends an attribute. Another run will be added if necessary,
+ * but we try to extend the last run in the runlist first.
+ * FIXME: what if there isn't enough contiguous space, we don't create
+ * multiple runs?
+ *
+ * *len: the desired new length of the attr (_not_ the amount to extend by)
+ */
X int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, int *len,
X int flags)
X {
@@ -111,34 +131,46 @@
X int rlen;
X ntfs_cluster_t cluster;
X int clen;
+
X if(attr->compressed)return EOPNOTSUPP;
X if(ino->record_count>1)return EOPNOTSUPP;
+
X if(attr->resident) {
X error = ntfs_make_attr_nonresident(ino,attr);
X if(error)


X return error;
X }
X

+ if( *len <= attr->allocated )
+ return 0; /* truely stupid things do sometimes happen */
+
X rl=attr->d.r.runlist;
X rlen=attr->d.r.len-1;
+
X if(rlen>=0)
X cluster=rl[rlen].cluster+rl[rlen].len;
X else
X /* no preference for allocation space */
X cluster=0;
- /* round up to multiple of cluster size */
- clen=(*len+ino->vol->clustersize-1)/ino->vol->clustersize;
+
+ /* calculate the extra space we need, and round up to multiple of cluster
+ * size to get number of new clusters needed */
+
+ clen=( (*len - attr->allocated ) + ino->vol->clustersize - 1 ) /
+ ino->vol->clustersize;
X if(clen==0)
X return 0;
+
X /* FIXME: try to allocate smaller pieces */
X error=ntfs_allocate_clusters(ino->vol,&cluster,&clen,
X flags|ALLOC_REQUIRE_SIZE);
X if(error)return error;
X attr->allocated += clen*ino->vol->clustersize;
- *len=clen*ino->vol->clustersize;
+ *len = attr->allocated;
+
X /* contiguous chunk */
X if(rlen>=0 && cluster==rl[rlen].cluster+rl[rlen].len){
- rl[rlen].len+=clen;
+ rl[rlen].len += clen;
X return 0;
X }
X ntfs_insert_run(attr,rlen+1,cluster,clen);
@@ -208,8 +240,10 @@
X v=attr->d.data;
X if(newsize){
X attr->d.data=ntfs_malloc(newsize);
- if(!attr->d.data)
+ if(!attr->d.data) {
+ ntfs_free(v);
X return ENOMEM;
+ }
X if(newsize>oldsize)
X ntfs_bzero((char*)attr->d.data+oldsize,
X newsize-oldsize);
@@ -231,7 +265,7 @@
X newlen=i+1;
X /* free unused clusters in current run, unless sparse */
X newcount=count;
- if(rl[i].cluster!=-1){
+ if(rl[i].cluster!=MAX_CLUSTER_T){
X int rounded=newsize-count*clustersize;
X rounded=(rounded+clustersize-1)/clustersize;
X error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster+rounded,
@@ -243,7 +277,7 @@
X }
X /* free all other runs */
X for(i++;i<attr->d.r.len;i++)
- if(rl[i].cluster!=-1){
+ if(rl[i].cluster!=MAX_CLUSTER_T){
X error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster,(int)rl[i].len);
X if(error)
X return error; /* FIXME: incomplete operation */
@@ -279,12 +313,20 @@
X if(aname){
X namelen=strlen(aname);
X name=ntfs_malloc(2*namelen);
+ if( !name )
+ return ENOMEM;
X ntfs_ascii2uni(name,aname,namelen);
X }else{
X name=0;
X namelen=0;
X }
- new_attr(ino,anum,name,namelen,&i,&found);
+
+ error = ntfs_new_attr(ino,anum,name,namelen,&i,&found,1);
+ if( error ) {
+ ntfs_free( name );


+ return error;
+ }
+

X if(found){
X ntfs_free(name);
X return EEXIST;
@@ -309,6 +351,10 @@
X }else
X attr->indexed=0;
X attr->d.data=ntfs_malloc(dsize);
+
+ if( !attr->d.data )
+ return ENOMEM;
+
X ntfs_memcpy(attr->d.data,data,dsize);
X return 0;
X }
@@ -366,6 +412,7 @@
X int namelen;
X void *data;
X ntfs_attribute *attr;
+ int error;
X
X type = NTFS_GETU32(attrdata);
X namelen = NTFS_GETU8(attrdata+9);
@@ -376,15 +423,30 @@
X {
X /* 1 Unicode character fits in 2 bytes */
X name=ntfs_malloc(2*namelen);
+ if( !name )
+ return ENOMEM;
+
X ntfs_memcpy(name,attrdata+NTFS_GETU16(attrdata+10),2*namelen);
X }
- new_attr(ino,type,name,namelen,&i,&found);
+
+ error = ntfs_new_attr(ino,type,name,namelen,&i,&found,1);
+ if( error ) {
+ if( name ) ntfs_free( name );


+ return error;
+ }
+

X /* We can have in one inode two attributes with type 0x00000030 (File Name)
X and without name */
X if(found && /*FIXME*/type!=ino->vol->at_file_name)
X {
X ntfs_process_runs(ino,ino->attrs+i,attrdata);
X return 0;
+ } else if( found ) {
+ /* Don't understand the above, but I know it leaks memory below
+ as it overwrites a found entry without freeing it. So here we
+ call ntfs_new_attr again but this time ask it to always allocate a
+ new entry */
+ ntfs_new_attr(ino,type,name,namelen,&i,&found,0);
X }
X attr=ino->attrs+i;
X attr->resident=NTFS_GETU8(attrdata+8)==0;
@@ -395,6 +457,8 @@
X attr->size=NTFS_GETU16(attrdata+0x10);
X data=attrdata+NTFS_GETU16(attrdata+0x14);
X attr->d.data = (void*)ntfs_malloc(attr->size);
+ if( !attr->d.data )
+ return ENOMEM;
X ntfs_memcpy(attr->d.data,data,attr->size);
X attr->indexed=NTFS_GETU16(attrdata+0x16);
X }else{
@@ -468,7 +532,7 @@
X copied=0;
X while(l){
X chunk=0;
- if(cluster==-1){
+ if(cluster==MAX_CLUSTER_T){
X /* sparse cluster */
X int l1;
X if((len-(s_vcn-vcn)) & 15)
@@ -503,9 +567,9 @@
X }
X got+=l1;
X comp1+=l1*clustersize;
- }while(cluster!=-1 && got<16); /* until empty run */
+ }while(cluster!=MAX_CLUSTER_T && got<16); /* until empty run */
X chunk=16*clustersize;
- if(cluster!=-1 || got==16)
+ if(cluster!=MAX_CLUSTER_T || got==16)
X /* uncompressible */
X comp1=comp;
X else{
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/attr.h linux/fs/ntfs/attr.h
--- v2.2.5/linux/fs/ntfs/attr.h Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/attr.h Mon Apr 12 10:05:58 1999
@@ -18,3 +18,7 @@
X int ntfs_read_zero(ntfs_io *dest,int size);
X int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr);
X int ntfs_attr_allnonresident(ntfs_inode *ino);
+int ntfs_new_attr( ntfs_inode *ino, int type, void *name, int namelen,
+ int *pos, int *found, int do_search );
+void ntfs_insert_run( ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
+ int len );
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/dir.c linux/fs/ntfs/dir.c
--- v2.2.5/linux/fs/ntfs/dir.c Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/dir.c Mon Apr 12 10:05:58 1999
@@ -1,7 +1,9 @@
X /*
X * dir.c
X *
- * Copyright (C) 1995-1997 Martin von Löwis
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 1999 Joseph Malicki
X */
X
X #include "ntfstypes.h"
@@ -67,7 +69,7 @@
X if(i<55)return (stack<<8)|((i-23)<<3)|3;
X if(i<120)return (stack<<10)|((i-55)<<4)|7;
X ntfs_error("Too many entries\n");
- return 0xFFFFFFFFFFFFFFFF;
+ return ~((ntfs_u64)0);
X }
X
X #if 0
@@ -166,6 +168,8 @@
X int nr_fix = s1/vol->blocksize+1;
X int hsize;
X char *record=ntfs_malloc(s1);
+ if( !record )
+ return ENOMEM;
X ntfs_bzero(record,s1);
X /* magic */
X ntfs_memcpy(record,"INDX",4);
@@ -356,8 +360,10 @@
X if(do_split){
X error=ntfs_split_record(walk,start,blocksize,usedsize);
X ntfs_free(start);
- }else
- ntfs_index_writeback(walk,start,walk->block,usedsize);
+ }else{
+ error=ntfs_index_writeback(walk,start,walk->block,usedsize);
+ if(error)return error;
+ }


X return 0;
X }
X

@@ -395,8 +401,9 @@
X goto out;
X }
X index = ntfs_malloc(ino->vol->index_recordsize);
- if(!index)
- goto out;
+ if(!index) {
+ error = ENOMEM; goto out;
+ }
X walk.dir = ino;
X walk.block = -1;
X walk.result = walk.new_entry = 0;
@@ -462,12 +469,12 @@
X ntfs_u16* name=(ntfs_u16*)(entry+0x52);
X ntfs_volume *vol=walk->dir->vol;
X for(i=0;i<lu && i<walk->namelen;i++)
- if(ntfs_my_toupper(vol,name[i])!=ntfs_my_toupper(vol,walk->name[i]))
+ if(ntfs_my_toupper(vol,NTFS_GETU16(name+i))!=ntfs_my_toupper(vol,NTFS_GETU16(walk->name+i)))
X break;
X if(i==lu && i==walk->namelen)return 0;
X if(i==lu)return 1;
X if(i==walk->namelen)return -1;
- if(ntfs_my_toupper(vol,name[i])<ntfs_my_toupper(vol,walk->name[i]))return 1;
+ if(ntfs_my_toupper(vol,NTFS_GETU16(name+i))<ntfs_my_toupper(vol,NTFS_GETU16(walk->name+i)))return 1;
X return -1;
X }
X
@@ -485,6 +492,9 @@
X int oldblock;
X ntfs_io io;
X
+ if( !record )
+ return ENOMEM;
+
X io.fn_put=ntfs_put;
X io.param=record;
X io.size=length;
@@ -607,7 +617,6 @@
X static int ntfs_getdir_iterate(ntfs_iterate_s *walk, char *start, char *entry)
X {
X int length;
- int retval=0;
X int cmp;
X
X if(walk->type==BY_POSITION)
@@ -647,7 +656,7 @@
X }
X entry+=length;
X }while(1);
- return retval;
+ return 0;
X }
X
X /* Tree walking is done using position numbers. The following numbers have
@@ -683,6 +692,9 @@
X char *root=ntfs_malloc(length);
X ntfs_io io;
X
+ if( !root )
+ return ENOMEM;
+
X io.fn_put=ntfs_put;
X io.param=root;
X io.size=length;
@@ -747,6 +759,8 @@
X /* are we still in the index root */
X if(*p_high==0){
X buf=ntfs_malloc(length=vol->mft_recordsize);
+ if( !buf )
+ return ENOMEM;
X io.fn_put=ntfs_put;
X io.param=buf;
X io.size=length;
@@ -762,6 +776,8 @@
X }else{ /* we are in an index record */
X length=ino->u.index.recordsize;
X buf=ntfs_malloc(length);
+ if( !buf )
+ return ENOMEM;
X io.fn_put=ntfs_put;
X io.param=buf;
X io.size=length;
@@ -821,6 +837,9 @@
X return 0;
X }
X buf=ntfs_malloc(length=attr->size);
+ if( !buf )
+ return ENOMEM;
+
X io.param=buf;
X io.size=length;
X error=ntfs_read_attr(ino,vol->at_bitmap,I30,0,&io);
@@ -920,8 +939,8 @@
X
X /* Fills out and creates an INDEX_ROOT attribute. */
X
-static int
-add_index_root (ntfs_inode *ino, int type)
+int
+ntfs_add_index_root (ntfs_inode *ino, int type)
X {
X ntfs_attribute *da;
X ntfs_u8 data[0x30]; /* 0x20 header, 0x10 last entry */
@@ -959,7 +978,7 @@
X error = ntfs_alloc_inode(dir, result, name, namelen, NTFS_AFLAG_DIR);
X if(error)
X goto out;
- error = add_index_root(result, 0x30);
+ error = ntfs_add_index_root(result, 0x30);
X if (error)
X goto out;
X /* Set directory bit */
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/dir.h linux/fs/ntfs/dir.h
--- v2.2.5/linux/fs/ntfs/dir.h Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/dir.h Mon Apr 12 10:05:58 1999
@@ -39,3 +39,4 @@
X int ntfs_getdir_byposition(ntfs_iterate_s *walk);
X int ntfs_mkdir(ntfs_inode* dir,const char* name,int namelen, ntfs_inode *ino);
X int ntfs_split_indexroot(ntfs_inode *ino);
+int ntfs_add_index_root( ntfs_inode *ino, int type );
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.2.5/linux/fs/ntfs/fs.c Tue Mar 23 14:35:48 1999
+++ linux/fs/ntfs/fs.c Mon Apr 12 10:05:58 1999
@@ -2,7 +2,7 @@
X * fs.c
X * NTFS driver for Linux 2.1
X *
- * Copyright (C) 1995-1997 Martin von Löwis
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
X * Copyright (C) 1996 Richard Russon
X * Copyright (C) 1996-1997 Régis Duchesne
X */
@@ -387,6 +387,8 @@
X if(error)
X return error;
X item=ntfs_malloc(ITEM_SIZE);
+ if( !item )
+ return ENOMEM;
X /* ntfs_getdir will place the directory entry into item,
X and the first long long is the MFT record number */
X walk.type=BY_NAME;
@@ -583,8 +585,6 @@
X int ret=ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino),block);
X ntfs_debug(DEBUG_OTHER, "bmap of %lx,block %x is %x\n",
X ino->i_ino,block,ret);
- ntfs_error("bmap of %lx,block %x is %x\n", ino->i_ino,block,ret);
- ntfs_error("super %x\n", ino->i_sb->s_blocksize);
X return (ret==-1) ? 0:ret;
X }
X
@@ -709,6 +709,7 @@
X #ifdef NTFS_IN_LINUX_KERNEL
X ino=&inode->u.ntfs_i;
X #else
+ /* FIXME: check for ntfs_malloc failure */
X ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
X inode->u.generic_ip=ino;
X #endif
@@ -818,6 +819,7 @@
X struct statfs fs;
X struct inode *mft;
X ntfs_volume *vol;
+ int error;
X
X ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
X vol=NTFS_SB2VOL(sb);
@@ -825,7 +827,9 @@
X fs.f_type=NTFS_SUPER_MAGIC;
X fs.f_bsize=vol->clustersize;
X
- fs.f_blocks=ntfs_get_volumesize(NTFS_SB2VOL(sb));
+ error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks );
+ if( error )
+ return error;
X fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
X fs.f_bavail=fs.f_bfree;
X
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c
--- v2.2.5/linux/fs/ntfs/inode.c Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/inode.c Mon Apr 12 10:05:58 1999
@@ -5,13 +5,18 @@
X * Copyright (C) 1996 Albert D. Cahalan
X * Copyright (C) 1996-1997 Régis Duchesne
X * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Steve Dodd
X */
X
X #include "ntfstypes.h"
+#include "ntfsendian.h"
X #include "struct.h"
X #include "inode.h"
X
X #include <linux/errno.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
X #include "macros.h"
X #include "attr.h"
X #include "super.h"
@@ -30,8 +35,8 @@
X ntfs_mft_record* records;
X } ntfs_disk_inode;
X
-static void
-fill_mft_header(ntfs_u8*mft,int record_size,int blocksize,
+void
+ntfs_fill_mft_header(ntfs_u8*mft,int record_size,int blocksize,
X int sequence_number)
X {
X int fixup_count = record_size / blocksize + 1;
@@ -98,7 +103,7 @@
X if(mdata->allocated<mdata->size+vol->mft_recordsize){
X size=ntfs_get_free_cluster_count(vol->bitmap)*vol->clustersize;
X block=vol->mft_recordsize;
- size=max(size/1000,block);
+ size=max(size/1000,mdata->size+vol->mft_recordsize);
X size=((size+block-1)/block)*block;
X /* require this to be a single chunk */
X error=ntfs_extend_attr(vol->mft_ino,mdata,&size,
@@ -141,7 +146,7 @@
X /* now fill in the MFT header for the new block */
X buf=ntfs_calloc(vol->mft_recordsize);
X if(!buf)return ENOMEM;
- fill_mft_header(buf,vol->mft_recordsize,vol->blocksize,0);
+ ntfs_fill_mft_header(buf,vol->mft_recordsize,vol->blocksize,0);
X ntfs_insert_fixups(buf,vol->blocksize);
X io.param=buf;
X io.size=vol->mft_recordsize;
@@ -149,6 +154,8 @@
X (rcount-1)*vol->mft_recordsize,&io);
X if(error)return error;
X if(io.size!=vol->mft_recordsize)return EIO;
+ error=ntfs_update_inode(vol->mft_ino);
+ if(error)return error;


X return 0;
X }
X

@@ -165,13 +172,16 @@
X /* (re-)allocate space if necessary */
X if(ino->record_count % 8==0)
X {
- int *old=ino->records;
- ino->records=ntfs_malloc((ino->record_count+8)*sizeof(int));
- if(old) {
+ int *new;
+ new = ntfs_malloc((ino->record_count+8)*sizeof(int));
+ if( !new )
+ return;
+ if( ino->records ) {
X for(i=0;i<ino->record_count;i++)
- ino->records[i]=old[i];
- ntfs_free(old);
+ new[i] = ino->records[i];
+ ntfs_free( ino->records );
X }
+ ino->records = new;
X }
X ino->records[ino->record_count]=mftno;
X ino->record_count++;
@@ -179,8 +189,10 @@
X do{
X type=NTFS_GETU32(it);
X len=NTFS_GETU32(it+4);
- if(type!=-1)
+ if(type!=-1) {
+ /* FIXME: check ntfs_insert_attribute for failure (e.g. no mem)? */
X ntfs_insert_attribute(ino,it);
+ }
X it+=len;
X }while(type!=-1); /* attribute list ends with type -1 */
X }
@@ -195,6 +207,8 @@
X int last_mft=-1;
X int len=*plen;
X mft=ntfs_malloc(ino->vol->mft_recordsize);
+ if( !mft )
+ return ENOMEM;
X while(len>8)
X {
X l=NTFS_GETU16(alist+4);
@@ -239,6 +253,8 @@
X return;
X }
X buf=ntfs_malloc(1024);
+ if( !buf )
+ return;
X delta=0;
X for(offset=0;datasize;datasize-=len)
X {
@@ -271,6 +287,8 @@
X ino->i_number=inum;
X ino->vol=vol;
X ino->attr=buf=ntfs_malloc(vol->mft_recordsize);
+ if( !buf )
+ return ENOMEM;
X error=ntfs_read_mft_record(vol,inum,ino->attr);
X if(error){
X ntfs_debug(DEBUG_OTHER, "init inode: %x failed\n",inum);
@@ -441,7 +459,7 @@
X int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
X ntfs_io *dest)
X {
- int datasize,rnum;
+ int rnum;
X ntfs_cluster_t cluster,s_cluster,vcn,len;
X int l,chunk,copied;
X int s_vcn;
@@ -449,26 +467,39 @@
X int error;
X
X clustersize=ino->vol->clustersize;
- datasize=attr->size;
X l=dest->size;
X if(l==0)
X return 0;
X if(dest->do_read)
X {
- if(offset>=datasize){
+ /* if read _starts_ beyond end of stream, return nothing */
+ if(offset>=attr->size){
X dest->size=0;
X return 0;
X }
- if(offset+l>=datasize)
- l=dest->size=datasize-offset;
- }else { /* fixed by CSA: if writing beyond end, extend attribute */
- if (offset+l>datasize) {
+
+ /* if read _extends_ beyond end of stream, return as much
+ initialised data as we have */
+ if(offset+l>=attr->size)
+ l=dest->size=attr->size-offset;
+
+ }else {
+ /* fixed by CSA: if writing beyond end, extend attribute */
+
+ /* if write extends beyond _allocated_ size, extend attrib */
+ if (offset+l>attr->allocated) {
X error=ntfs_resize_attr(ino,attr,offset+l);
X if(error)
X return error;
X }
- if (offset+l > attr->initialized)
+
+ /* the amount of initialised data has increased; update */
+ /* FIXME: shouldn't we zero-out the section between the old
+ initialised length and the write start? */
+ if (offset+l > attr->initialized) {
X attr->initialized = offset+l;
+ attr->size = offset+l;
+ }
X }
X if(attr->resident)
X {
@@ -565,7 +596,6 @@
X {
X int rnum;
X ntfs_attribute *data;
- ntfs_error("bmap %x\n",vcn);
X data=ntfs_find_attr(ino,ino->vol->at_data,0);
X /* It's hard to give an error code */
X if(!data)return -1;
@@ -583,7 +613,6 @@
X vcn>data->d.r.runlist[rnum].len;rnum++)
X vcn-=data->d.r.runlist[rnum].len;
X
- ntfs_error("result %x\n",data->d.r.runlist[rnum].cluster+vcn);
X return data->d.r.runlist[rnum].cluster+vcn;
X }
X
@@ -655,7 +684,7 @@
X
X *(rec+offset)|=coffs++;
X
- if(rl[i].cluster==0) /*compressed run*/
+ if(rl[i].cluster==MAX_CLUSTER_T) /*compressed run*/
X /*nothing*/;
X else if(rclus>-0x80 && rclus<0x7F){
X *(rec+offset)|=0x10;
@@ -768,7 +797,8 @@
X NTFS_PUTU16(buf+0xA,asize);
X ntfs_memcpy(buf+asize,attr->name,2*attr->namelen);
X asize+=2*attr->namelen;
- asize=(asize+7) & ~7;
+ /* SRD: you whaaa?
+ asize=(asize+7) & ~7;*/
X }
X /* asize points at the beginning of the data */
X NTFS_PUTU16(buf+0x20,asize);
@@ -841,7 +871,12 @@
X if(error)
X return error;
X }
- next=(next+7) & ~7; /* align to DWORD */
+ /* SRD: umm..
+ next=(next+7) & ~7; */
+ /* is this setting the length? if so maybe we could get
+ away with rounding up so long as we set the length first..
+ ..except, is the length the only way to get to the next attr?
+ */
X NTFS_PUTU16(rec+offset+4,next-offset);
X offset=next;
X #endif
@@ -1038,7 +1073,8 @@
X data=ntfs_find_attr(vol->mft_ino,vol->at_data,0);
X length=data->size/vol->mft_recordsize;
X
- for (byte = 3; 8*byte < length; byte++)
+ /* SRD: start at byte 0: bits for system files _are_ already set in bitmap */
+ for (byte = 0; 8*byte < length; byte++)
X {
X value = buffer[byte];
X if(value==0xFF)
@@ -1064,7 +1100,7 @@
X mft=ino->attr;
X
X ntfs_bzero(mft, vol->mft_recordsize);
- fill_mft_header(mft,vol->mft_recordsize,vol->blocksize,
+ ntfs_fill_mft_header(mft,vol->mft_recordsize,vol->blocksize,
X ino->sequence_number);
X return 0;
X }
@@ -1108,6 +1144,8 @@
X /* work out the size */
X size = 0x42 + 2 * length;
X data = ntfs_malloc(size);
+ if( !data )
+ return ENOMEM;
X ntfs_bzero(data,size);
X
X /* search for a position */
@@ -1191,7 +1229,7 @@
X {
X ntfs_io io;
X int error;
- ntfs_u8 buffer[1];
+ ntfs_u8 buffer[2];
X ntfs_volume* vol=dir->vol;
X int byte,bit;
X
@@ -1230,7 +1268,7 @@
X */
X /* get the sequence number */
X io.param = buffer;
- io.size = 0x10;
+ io.size = 2;
X error = ntfs_read_attr(vol->mft_ino, vol->at_data, 0,
X result->i_number*vol->mft_recordsize+0x10,&io);
X if(error)
@@ -1238,10 +1276,17 @@
X result->sequence_number=NTFS_GETU16(buffer)+1;
X result->vol=vol;
X result->attr=ntfs_malloc(vol->mft_recordsize);
+ if( !result->attr )
+ return ENOMEM;
X result->attr_count=0;
X result->attrs=0;
X result->record_count=1;
X result->records=ntfs_malloc(8*sizeof(int));
+ if( !result->records ) {
+ ntfs_free( result->attr );
+ result->attr = 0;
+ return ENOMEM;
+ }
X result->records[0]=result->i_number;
X error=add_mft_header(result);
X if(error)
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/inode.h linux/fs/ntfs/inode.h
--- v2.2.5/linux/fs/ntfs/inode.h Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/inode.h Mon Apr 12 10:05:58 1999
@@ -26,3 +26,5 @@
X int ntfs_decompress_run(unsigned char **data, int *length, ntfs_cluster_t *cluster,
X int *ctype);
X void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l);
+void ntfs_fill_mft_header( ntfs_u8 *mft, int recordsize, int blocksize,
+ int sequence_number );
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/ntfsendian.h linux/fs/ntfs/ntfsendian.h
--- v2.2.5/linux/fs/ntfs/ntfsendian.h Thu Jan 7 15:11:40 1999
+++ linux/fs/ntfs/ntfsendian.h Mon Apr 12 10:05:58 1999
@@ -1,8 +1,9 @@
X /*
X * ntfsendian.h
X *
- * Copyright (C) 1998 Martin von Löwis
+ * Copyright (C) 1998, 1999 Martin von Löwis
X * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Werner Seiler
X */
X
X #ifdef __linux__
@@ -36,9 +37,9 @@
X #ifdef __BIG_ENDIAN
X
X /* We hope its big-endian, not PDP-endian :) */
-#define CPU_TO_LE16(a) ((((a)&0xF) << 8)|((a) >> 8))
-#define CPU_TO_LE32(a) ((((a) & 0xF) << 24) | (((a) & 0xF0) << 8) | \
- (((a) & 0xF00) >> 8) | ((a) >> 24))
+#define CPU_TO_LE16(a) ((((a)&0xFF) << 8)|((a) >> 8))
+#define CPU_TO_LE32(a) ((((a) & 0xFF) << 24) | (((a) & 0xFF00) << 8) | \
+ (((a) & 0xFF0000) >> 8) | ((a) >> 24))
X #define CPU_TO_LE64(a) ((CPU_TO_LE32(a)<<32)|CPU_TO_LE32((a)>>32)
X
X #define LE16_TO_CPU(a) CPU_TO_LE16(a)
@@ -55,7 +56,7 @@
X
X #define NTFS_GETU8(p) (*(ntfs_u8*)(p))
X #define NTFS_GETU16(p) ((ntfs_u16)LE16_TO_CPU(*(ntfs_u16*)(p)))
-#define NTFS_GETU24(p) (NTFS_GETU32(p) & 0xFFFFFF)
+#define NTFS_GETU24(p) ((ntfs_u32)NTFS_GETU16(p) | ((ntfs_u32)NTFS_GETU8(((char*)(p))+2)<<16))
X #define NTFS_GETU32(p) ((ntfs_u32)LE32_TO_CPU(*(ntfs_u32*)(p)))
X #define NTFS_GETU40(p) ((ntfs_u64)NTFS_GETU32(p)|(((ntfs_u64)NTFS_GETU8(((char*)(p))+4))<<32))
X #define NTFS_GETU48(p) ((ntfs_u64)NTFS_GETU32(p)|(((ntfs_u64)NTFS_GETU16(((char*)(p))+4))<<32))
@@ -75,9 +76,9 @@
X #define NTFS_GETS16(p) ((ntfs_s16)LE16_TO_CPU(*(short*)(p)))
X #define NTFS_GETS24(p) (NTFS_GETU24(p) < 0x800000 ? (int)NTFS_GETU24(p) : (int)(NTFS_GETU24(p) - 0x1000000))
X #define NTFS_GETS32(p) ((ntfs_s32)LE32_TO_CPU(*(int*)(p)))
-#define NTFS_GETS40(p) (((ntfs_s64)NTFS_GETS32(p)) | (((ntfs_s64)NTFS_GETS8(((char*)(p))+4)) << 32))
-#define NTFS_GETS48(p) (((ntfs_s64)NTFS_GETS32(p)) | (((ntfs_s64)NTFS_GETS16(((char*)(p))+4)) << 32))
-#define NTFS_GETS56(p) (((ntfs_s64)NTFS_GETS32(p)) | (((ntfs_s64)NTFS_GETS24(((char*)(p))+4)) << 32))
+#define NTFS_GETS40(p) (((ntfs_s64)NTFS_GETU32(p)) | (((ntfs_s64)NTFS_GETS8(((char*)(p))+4)) << 32))
+#define NTFS_GETS48(p) (((ntfs_s64)NTFS_GETU32(p)) | (((ntfs_s64)NTFS_GETS16(((char*)(p))+4)) << 32))
+#define NTFS_GETS56(p) (((ntfs_s64)NTFS_GETU32(p)) | (((ntfs_s64)NTFS_GETS24(((char*)(p))+4)) << 32))
X #define NTFS_GETS64(p) ((ntfs_s64)NTFS_GETU64(p))
X
X #define NTFS_PUTS8(p,v) NTFS_PUTU8(p,v)
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/ntfstypes.h linux/fs/ntfs/ntfstypes.h
--- v2.2.5/linux/fs/ntfs/ntfstypes.h Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/ntfstypes.h Mon Apr 12 10:05:58 1999
@@ -1,12 +1,12 @@
X /*
- * types.h
+ * ntfstypes.h
X * This file defines four things:
X * - generic platform independent fixed-size types (e.g. ntfs_u32)
X * - specific fixed-size types (e.g. ntfs_offset_t)
X * - macros that read and write those types from and to byte arrays
X * - types derived from OS specific ones
X *
- * Copyright (C) 1996,1998 Martin von Löwis
+ * Copyright (C) 1996,1998, 1999 Martin von Löwis
X */
X
X #ifdef NTFS_IN_LINUX_KERNEL
@@ -52,6 +52,10 @@
X #ifndef NTFS_CLUSTER_T
X #define NTFS_CLUSTER_T
X typedef u32 ntfs_cluster_t;
+#endif
+
+#ifndef MAX_CLUSTER_T
+#define MAX_CLUSTER_T (~((ntfs_cluster_t)0))
X #endif
X
X /* architecture independent macros */
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/super.c linux/fs/ntfs/super.c
--- v2.2.5/linux/fs/ntfs/super.c Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/super.c Mon Apr 12 10:05:58 1999
@@ -1,8 +1,9 @@
X /*
X * super.c
X *
- * Copyright (C) 1995-1997 Martin von Löwis
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
X * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1999 Steve Dodd
X */
X
X #include "ntfstypes.h"
@@ -113,12 +114,14 @@
X ntfs_io io;
X #define UPCASE_LENGTH 256
X upcase->vol->upcase = ntfs_malloc(2*UPCASE_LENGTH);
- upcase->vol->upcase_length = UPCASE_LENGTH;
+ if( !upcase->vol->upcase )
+ return;
X io.fn_put=ntfs_put;
X io.fn_get=0;
X io.param=(char*)upcase->vol->upcase;
X io.size=2*UPCASE_LENGTH;
X ntfs_read_attr(upcase,upcase->vol->at_data,0,0,&io);
+ upcase->vol->upcase_length = io.size;
X }
X
X static int
@@ -246,11 +249,22 @@


X return 0;
X }
X

-int ntfs_get_volumesize(ntfs_volume *vol)
+/*
+ * Writes the volume size into vol_size. Returns 0 if successful
+ * or error.
+ */
+int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size )
X {
X ntfs_io io;
- char *cluster0=ntfs_malloc(vol->clustersize);
X ntfs_u64 size;
+ char *cluster0;
+
+ if( !vol_size )
+ return EFAULT;
+
+ cluster0=ntfs_malloc(vol->clustersize);
+ if( !cluster0 )
+ return ENOMEM;
X
X io.fn_put=ntfs_put;
X io.fn_get=ntfs_get;
@@ -262,7 +276,8 @@
X ntfs_free(cluster0);
X /* FIXME: more than 2**32 cluster */
X /* FIXME: gcc will emit udivdi3 if we don't truncate it */
- return ((unsigned int)size)/vol->clusterfactor;
+ *vol_size = ((unsigned long)size)/vol->clusterfactor;
+ return 0;
X }
X
X static int nc[16]={4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0};
@@ -337,7 +352,7 @@
X int start,stop=0,in=0;
X /* special case searching for a single block */
X if(*cnt==1){
- while(l && *cnt==0xFF){
+ while(l && *bits==0xFF){
X bits++;
X *loc+=8;
X l--;
@@ -398,7 +413,7 @@
X
X io.fn_put=ntfs_put;
X io.fn_get=ntfs_get;
- bsize=(cnt+(loc & 7)+7) & ~7; /* round up to multiple of 8*/
+ bsize=(cnt+(loc & 7)+7) >> 3; /* round up to multiple of 8*/
X bits=ntfs_malloc(bsize);
X io.param=bits;
X io.size=bsize;
@@ -418,7 +433,7 @@
X else
X *it &= ~(1<<(locit%8));
X cnt--;locit++;
- if(locit%8==7)
+ if(locit%8==0)
X it++;
X }
X while(cnt>8){ /*process full bytes */
@@ -456,10 +471,13 @@
X unsigned char *bits;
X ntfs_io io;
X int error=0,found=0;
- int loc,cnt,bloc=-1,bcnt=0;
+ int cnt,bloc=-1,bcnt=0;
X int start;
+ ntfs_cluster_t loc;
X
X bits=ntfs_malloc(2048);
+ if( !bits )
+ return ENOMEM;
X io.fn_put=ntfs_put;
X io.fn_get=ntfs_get;
X io.param=bits;
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/super.h linux/fs/ntfs/super.h
--- v2.2.5/linux/fs/ntfs/super.h Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/super.h Mon Apr 12 10:05:58 1999
@@ -10,7 +10,7 @@
X #define ALLOC_REQUIRE_SIZE 2
X
X int ntfs_get_free_cluster_count(ntfs_inode *bitmap);
-int ntfs_get_volumesize(ntfs_volume *vol);
+int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size );
X int ntfs_init_volume(ntfs_volume *vol,char *boot);
X int ntfs_load_special_files(ntfs_volume *vol);
X int ntfs_release_volume(ntfs_volume *vol);
diff -u --recursive --new-file v2.2.5/linux/fs/ntfs/support.c linux/fs/ntfs/support.c
--- v2.2.5/linux/fs/ntfs/support.c Mon Jan 4 15:08:17 1999
+++ linux/fs/ntfs/support.c Mon Apr 12 10:05:58 1999
@@ -246,6 +246,10 @@
X if(!(vol->nct & nct_uni_xlate))goto inval;
X /* realloc */
X buf=ntfs_malloc(*out_len+3);
+ if( !buf ) {
+ ntfs_free( result );
+ return ENOMEM;
+ }
X memcpy(buf,result,o);
X ntfs_free(result);
X result=buf;
diff -u --recursive --new-file v2.2.5/linux/fs/open.c linux/fs/open.c
--- v2.2.5/linux/fs/open.c Tue Mar 23 14:35:48 1999
+++ linux/fs/open.c Fri Apr 16 14:21:39 1999
@@ -69,6 +69,10 @@
X int error;
X struct iattr newattrs;
X
+ /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
+ if ((off_t) length < 0)
+ return -EINVAL;
+
X down(&inode->i_sem);
X newattrs.ia_size = length;
X newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
@@ -294,11 +298,16 @@
X /* Clear the capabilities if we switch to a non-root user */
X if (current->uid)
X cap_clear(current->cap_effective);
-
+ else
+ current->cap_effective = current->cap_permitted;
+
X dentry = namei(filename);
X res = PTR_ERR(dentry);
X if (!IS_ERR(dentry)) {
X res = permission(dentry->d_inode, mode);
+ /* SuS v2 requires we report a read only fs too */
+ if(!res && (mode & S_IWOTH) && IS_RDONLY(dentry->d_inode))
+ res = -EROFS;
X dput(dentry);
X }
X
diff -u --recursive --new-file v2.2.5/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.2.5/linux/fs/proc/link.c Mon Sep 28 10:51:35 1998
+++ linux/fs/proc/link.c Mon Apr 12 16:18:26 1999
@@ -158,7 +158,7 @@
X path = tmp;
X } else {
X path = d_path(dentry, tmp, PAGE_SIZE);
- len = tmp + PAGE_SIZE - path;
+ len = tmp + PAGE_SIZE - 1 - path;
X }
X
X if (len < buflen)
diff -u --recursive --new-file v2.2.5/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.2.5/linux/fs/smbfs/dir.c Tue Dec 22 14:16:57 1998
+++ linux/fs/smbfs/dir.c Mon Apr 12 10:03:45 1999
@@ -423,9 +423,6 @@
X printk("smb_create: creating %s/%s, mode=%d\n",
X dentry->d_parent->d_name.name, dentry->d_name.name, mode);
X #endif
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > SMB_MAXNAMELEN)
- goto out;
X
X smb_invalid_dir_cache(dir);
X error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
@@ -439,7 +436,6 @@
X dentry->d_parent->d_name.name, dentry->d_name.name, error);
X #endif
X }
-out:


X return error;
X }
X

@@ -449,17 +445,12 @@
X {
X int error;
X
- error = -ENAMETOOLONG;
- if (dentry->d_name.len > SMB_MAXNAMELEN)
- goto out;
-
X smb_invalid_dir_cache(dir);
X error = smb_proc_mkdir(dentry);
X if (!error)
X {
X error = smb_instantiate(dentry, 0, 0);
X }
-out:


X return error;
X }
X

@@ -514,11 +505,6 @@
X {
X int error;
X
- error = -ENAMETOOLONG;
- if (old_dentry->d_name.len > SMB_MAXNAMELEN ||
- new_dentry->d_name.len > SMB_MAXNAMELEN)
- goto out;
-
X /*
X * Close any open files, and check whether to delete the
X * target before attempting the rename.
@@ -537,6 +523,7 @@
X #endif
X goto out;
X }
+ /* FIXME */
X d_delete(new_dentry);
X }
X
@@ -547,7 +534,6 @@
X {
X smb_renew_times(old_dentry);
X smb_renew_times(new_dentry);
- d_move(old_dentry, new_dentry);
X }
X out:
X return error;
diff -u --recursive --new-file v2.2.5/linux/fs/super.c linux/fs/super.c
--- v2.2.5/linux/fs/super.c Fri Jan 8 22:36:14 1999
+++ linux/fs/super.c Mon Apr 12 10:03:45 1999
@@ -559,6 +559,7 @@
X s->s_dev = dev;
X s->s_flags = flags;
X s->s_dirt = 0;
+ sema_init(&s->s_vfs_rename_sem,1);
X /* N.B. Should lock superblock now ... */
X if (!type->read_super(s, data, silent))
X goto out_fail;
diff -u --recursive --new-file v2.2.5/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.2.5/linux/fs/sysv/namei.c Tue Mar 23 14:35:48 1999
+++ linux/fs/sysv/namei.c Mon Apr 12 10:03:45 1999
@@ -594,8 +594,8 @@


X * Anybody can rename anything with this: the permission checks are left to the
X * higher-level routines.
X */

-static int do_sysv_rename(struct inode * old_dir, struct dentry * old_dentry,


- struct inode * new_dir, struct dentry * new_dentry)

+int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
+ struct inode * new_dir, struct dentry * new_dentry)


X {
X struct inode * old_inode, * new_inode;

X struct buffer_head * old_bh, * new_bh, * dir_bh;
@@ -628,20 +628,8 @@


X new_bh = NULL;
X }
X }
- if (new_inode == old_inode) {
- retval = 0;
- goto end_rename;
- }
X if (S_ISDIR(old_inode->i_mode)) {
- retval = -EINVAL;
- if (is_subdir(new_dentry, old_dentry))
- goto end_rename;
X if (new_inode) {

- if (new_dentry->d_count > 1)
- shrink_dcache_parent(new_dentry);
- retval = -EBUSY;
- if (new_dentry->d_count > 1)
- goto end_rename;
X retval = -ENOTEMPTY;

X if (!empty_dir(new_inode))
X goto end_rename;
@@ -696,37 +684,10 @@
X mark_inode_dirty(new_dir);
X }
X }


- d_move(old_dentry, new_dentry);
X retval = 0;
X end_rename:
X brelse(dir_bh);
X brelse(old_bh);
X brelse(new_bh);
X return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */

-int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,


- struct inode * new_dir, struct dentry * new_dentry)

-{
- static struct wait_queue * wait = NULL;
- static int lock = 0;
- int result;
-
- while (lock)
- sleep_on(&wait);
- lock = 1;

- result = do_sysv_rename(old_dir, old_dentry,


- new_dir, new_dentry);
- lock = 0;
- wake_up(&wait);
- return result;
X }

diff -u --recursive --new-file v2.2.5/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.2.5/linux/fs/ufs/namei.c Tue Jan 19 11:32:52 1999
+++ linux/fs/ufs/namei.c Mon Apr 12 10:03:45 1999
@@ -250,12 +250,6 @@
X swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X
- if (namelen > UFS_MAXNAMLEN)


- {
- *err = -ENAMETOOLONG;
- return NULL;
- }
-
X if (!namelen)
X return NULL;
X /*

@@ -469,10 +463,6 @@


X sb = dir->i_sb;

X flags = sb->u.ufs_sb.s_flags;
X swab = sb->u.ufs_sb.s_swab;
-
- err = -ENAMETOOLONG;
- if (dentry->d_name.len > UFS_MAXNAMLEN)
- goto out;
X
X inode = ufs_new_inode (dir, mode, &err);
X if (!inode)
@@ -528,10 +518,6 @@


X sb = dir->i_sb;

X flags = sb->u.ufs_sb.s_flags;
X swab = sb->u.ufs_sb.s_swab;
-
- err = -ENAMETOOLONG;
- if (dentry->d_name.len > UFS_MAXNAMLEN)
- goto out;
X
X err = -EMLINK;
X if (dir->i_nlink >= UFS_LINK_MAX)
@@ -670,10 +656,6 @@
X swab = sb->u.ufs_sb.s_swab;
X
X UFSD(("ENTER\n"))
-
- retval = -ENAMETOOLONG;
- if (dentry->d_name.len > UFS_MAXNAMLEN)
- goto out;
X
X retval = -ENOENT;
X bh = ufs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
@@ -687,14 +669,12 @@
X if (SWAB32(de->d_ino) != inode->i_ino)


X goto end_rmdir;
X
+ retval = -ENOTEMPTY;

X if (!ufs_empty_dir (inode))
- retval = -ENOTEMPTY;
- else if (SWAB32(de->d_ino) != inode->i_ino)


- retval = -ENOENT;
- else {

- retval = ufs_delete_entry (dir, de, bh);


- dir->i_version = ++event;
- }
+ goto end_rmdir;
+

+ retval = ufs_delete_entry (dir, de, bh);


+ dir->i_version = ++event;
X if (retval)
X goto end_rmdir;
X mark_buffer_dirty(bh, 1);

@@ -717,7 +697,6 @@


X
X end_rmdir:
X brelse (bh);
-out:

X UFSD(("EXIT\n"))
X
X return retval;
@@ -735,10 +714,6 @@


X sb = dir->i_sb;

X flags = sb->u.ufs_sb.s_flags;
X swab = sb->u.ufs_sb.s_swab;
-
- retval = -ENAMETOOLONG;
- if (dentry->d_name.len > UFS_MAXNAMLEN)
- goto out;
X
X retval = -ENOENT;
X bh = ufs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
@@ -779,7 +754,6 @@


X
X end_unlink:
X brelse (bh);
-out:
X return retval;
X }
X

@@ -881,9 +855,6 @@


X if (S_ISDIR(inode->i_mode))
X return -EPERM;
X
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return -EPERM;
-

X if (inode->i_nlink >= UFS_LINK_MAX)
X return -EMLINK;
X
@@ -912,17 +883,10 @@
X ((struct ufs_dir_entry *) ((char *) buffer + \
X SWAB16(((struct ufs_dir_entry *) buffer)->d_reclen)))->d_ino


X /*
- * rename uses retrying to avoid race-conditions: at least they should be
- * minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
X * Anybody can rename anything with this: the permission checks are left to the
X * higher-level routines.
X */

-static int do_ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
+int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,


X struct inode * new_dir, struct dentry * new_dentry )
X {

X struct super_block * sb;
@@ -941,9 +905,6 @@
X old_inode = new_inode = NULL;


X old_bh = new_bh = dir_bh = NULL;

X new_de = NULL;
- retval = -ENAMETOOLONG;
- if (old_dentry->d_name.len > UFS_MAXNAMLEN)
- goto end_rename;
X
X old_bh = ufs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
X /*
@@ -967,25 +928,14 @@


X DQUOT_INIT(new_inode);
X }
X }
- retval = 0;
- if (new_inode == old_inode)
- goto end_rename;
X if (S_ISDIR(old_inode->i_mode)) {
- retval = -EINVAL;
- if (is_subdir(new_dentry, old_dentry))
- goto end_rename;
X if (new_inode) {
- /* Prune any children before testing for busy */
- if (new_dentry->d_count > 1)
- shrink_dcache_parent(new_dentry);
- retval = -EBUSY;
- if (new_dentry->d_count > 1)
- goto end_rename;
X retval = -ENOTEMPTY;

X if (!ufs_empty_dir (new_inode))


X goto end_rename;
X }
X
+ retval = -EIO;

X dir_bh = ufs_bread (old_inode, 0, 0, &retval);


X if (!dir_bh)
X goto end_rename;

@@ -1042,8 +992,6 @@


X wait_on_buffer (new_bh);
X }
X
- /* Update the dcache */
- d_move(old_dentry, new_dentry);
X retval = 0;

X end_rename:
X brelse (dir_bh);
@@ -1054,36 +1002,3 @@
X
X return retval;
X }


-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- *
- * In the second extended file system, we use a lock flag stored in the memory
- * super-block. This way, we really lock other renames only if they occur
- * on the same file system
- */

-int ufs_rename (struct inode * old_dir, struct dentry *old_dentry,


- struct inode * new_dir, struct dentry *new_dentry )
-{
- int result;
-

- UFSD(("ENTER\n"))
-
- while (old_dir->i_sb->u.ufs_sb.s_rename_lock)
- sleep_on (&old_dir->i_sb->u.ufs_sb.s_rename_wait);
- old_dir->i_sb->u.ufs_sb.s_rename_lock = 1;
- result = do_ufs_rename (old_dir, old_dentry, new_dir, new_dentry);
- old_dir->i_sb->u.ufs_sb.s_rename_lock = 0;
- wake_up (&old_dir->i_sb->u.ufs_sb.s_rename_wait);
-
- UFSD(("EXIT\n"))
-
- return result;
-}
-
diff -u --recursive --new-file v2.2.5/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.2.5/linux/fs/ufs/super.c Tue Jan 19 11:32:52 1999
+++ linux/fs/ufs/super.c Mon Apr 12 10:03:45 1999
@@ -125,7 +125,7 @@
X printk(" cssize: %u\n", SWAB32(usb1->fs_cssize));
X printk(" cgsize: %u\n", SWAB32(usb1->fs_cgsize));
X printk(" fstodb: %u\n", SWAB32(usb1->fs_fsbtodb));
- printk(" contigsumsize: %d\n", SWAB32(usb3->fs_u.fs_44.fs_contigsumsize));
+ printk(" contigsumsize: %d\n", SWAB32(usb3->fs_u2.fs_44.fs_contigsumsize));
X printk(" postblformat: %u\n", SWAB32(usb3->fs_postblformat));
X printk(" nrpos: %u\n", SWAB32(usb3->fs_nrpos));
X printk(" ndir %u\n", SWAB32(usb1->fs_cstotal.cs_ndir));
@@ -269,10 +269,12 @@
X ufs_set_opt (*mount_options, UFSTYPE_SUN);
X else if (!strcmp (value, "44bsd"))
X ufs_set_opt (*mount_options, UFSTYPE_44BSD);
- else if (!strcmp (value, "next"))
- ufs_set_opt (*mount_options, UFSTYPE_NEXT);
+ else if (!strcmp (value, "nextstep"))
+ ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP);
X else if (!strcmp (value, "openstep"))
X ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
+ else if (!strcmp (value, "sunx86"))
+ ufs_set_opt (*mount_options, UFSTYPE_SUNx86);
X else {
X printk ("UFS-fs: Invalid type option: %s\n", value);
X return 0;
@@ -463,7 +465,7 @@
X }
X if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) {
X printk("You didn't specify the type of your ufs filesystem\n\n"
- " mount -t ufs -o ufstype=sun|44bsd|old|next|openstep ....\n\n"
+ " mount -t ufs -o ufstype=sun|sunx86|44bsd|old|nextstep|openstep ....\n\n"
X ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
X "default is ufstype=old\n");
X ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD);
@@ -495,6 +497,16 @@
X flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN;
X break;
X
+ case UFS_MOUNT_UFSTYPE_SUNx86:
+ UFSD(("ufstype=sunx86\n"))
+ uspi->s_fsize = block_size = 1024;
+ uspi->s_fmask = ~(1024 - 1);
+ uspi->s_fshift = 10;
+ uspi->s_sbsize = super_block_size = 2048;
+ uspi->s_sbbase = 0;
+ flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN;
+ break;
+
X case UFS_MOUNT_UFSTYPE_OLD:
X UFSD(("ufstype=old\n"))
X uspi->s_fsize = block_size = 1024;
@@ -509,8 +521,8 @@
X }
X break;
X
- case UFS_MOUNT_UFSTYPE_NEXT:
- UFSD(("ufstype=next\n"))
+ case UFS_MOUNT_UFSTYPE_NEXTSTEP:
+ UFSD(("ufstype=nextstep\n"))
X uspi->s_fsize = block_size = 1024;
X uspi->s_fmask = ~(1024 - 1);
X uspi->s_fshift = 10;
@@ -518,7 +530,7 @@
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(KERN_INFO "ufstype=next is supported read-only\n");
+ printk(KERN_INFO "ufstype=nextstep is supported read-only\n");
X sb->s_flags |= MS_RDONLY;
X }
X break;
@@ -579,10 +591,9 @@
X }
X #endif
X
- if ((((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
- UFS_MOUNT_UFSTYPE_NEXT) ||
- ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
- UFS_MOUNT_UFSTYPE_OPENSTEP)) && uspi->s_sbbase < 256) {
+ if ((((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP)
+ || ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_OPENSTEP))
+ && uspi->s_sbbase < 256) {
X ubh_brelse_uspi(uspi);
X ubh = NULL;
X uspi->s_sbbase += 8;
@@ -627,9 +638,10 @@
X * If not, make it read only.
X */
X if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) ||
- ((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
- (((flags & UFS_ST_MASK) == UFS_ST_SUN) &&
- (ufs_get_fs_state(usb3) == (UFS_FSOK - SWAB32(usb1->fs_time))))) {
+ ((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
+ (((flags & UFS_ST_MASK) == UFS_ST_SUN ||
+ (flags & UFS_ST_MASK) == UFS_ST_SUNx86) &&
+ (ufs_get_fs_state(usb1, usb3) == (UFS_FSOK - SWAB32(usb1->fs_time))))) {
X switch(usb1->fs_clean) {
X case UFS_FSCLEAN:
X UFSD(("fs is clean\n"))
@@ -649,8 +661,7 @@
X sb->s_flags |= MS_RDONLY;
X break;
X default:
- printk("ufs_read_super: can't grok fs_clean 0x%x\n",
- usb1->fs_clean);
+ printk("ufs_read_super: can't grok fs_clean 0x%x\n", usb1->fs_clean);
X sb->s_flags |= MS_RDONLY;
X break;
X }
@@ -694,7 +705,7 @@
X uspi->s_nindir = SWAB32(usb1->fs_nindir);
X uspi->s_inopb = SWAB32(usb1->fs_inopb);
X uspi->s_nspf = SWAB32(usb1->fs_nspf);
- uspi->s_npsect = SWAB32(usb1->fs_npsect);
+ uspi->s_npsect = ufs_get_fs_npsect(usb1, usb3);
X uspi->s_interleave = SWAB32(usb1->fs_interleave);
X uspi->s_trackskew = SWAB32(usb1->fs_trackskew);
X uspi->s_csaddr = SWAB32(usb1->fs_csaddr);
@@ -706,7 +717,7 @@
X uspi->s_ipg = SWAB32(usb1->fs_ipg);
X uspi->s_fpg = SWAB32(usb1->fs_fpg);
X uspi->s_cpc = SWAB32(usb2->fs_cpc);
- uspi->s_contigsumsize = SWAB32(usb3->fs_u.fs_44.fs_contigsumsize);
+ uspi->s_contigsumsize = SWAB32(usb3->fs_u2.fs_44.fs_contigsumsize);
X uspi->s_qbmask = ufs_get_fs_qbmask(usb3);
X uspi->s_qfmask = ufs_get_fs_qfmask(usb3);
X uspi->s_postblformat = SWAB32(usb3->fs_postblformat);


@@ -734,8 +745,6 @@
X

X sb->u.ufs_sb.s_flags = flags;
X sb->u.ufs_sb.s_swab = swab;
- sb->u.ufs_sb.s_rename_lock = 0;
- sb->u.ufs_sb.s_rename_wait = NULL;
X
X sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL);
X
@@ -776,8 +785,9 @@
X
X if (!(sb->s_flags & MS_RDONLY)) {
X usb1->fs_time = SWAB32(CURRENT_TIME);
- if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN)
- ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time));
+ if ((flags & UFS_ST_MASK) == UFS_ST_SUN
+ || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+ ufs_set_fs_state(usb1, usb3, UFS_FSOK - SWAB32(usb1->fs_time));
X ubh_mark_buffer_dirty (USPI_UBH, 1);
X }
X sb->s_dirt = 0;
@@ -842,8 +852,9 @@
X if (*mount_flags & MS_RDONLY) {
X ufs_put_cylinder_structures(sb);
X usb1->fs_time = SWAB32(CURRENT_TIME);
- if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN)
- ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time));
+ if ((flags & UFS_ST_MASK) == UFS_ST_SUN
+ || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+ ufs_set_fs_state(usb1, usb3, UFS_FSOK - SWAB32(usb1->fs_time));
X ubh_mark_buffer_dirty (USPI_UBH, 1);
X sb->s_dirt = 0;
X sb->s_flags |= MS_RDONLY;
diff -u --recursive --new-file v2.2.5/linux/fs/ufs/util.h linux/fs/ufs/util.h


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 24'
echo 'File patch-2.2.6 is continued in part 25'
echo 25 > _shar_seq_.tmp

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part27

#!/bin/sh
# this is part 27 of a 34 - part archive


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

if test "$Scheck" != 27; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&
X

-#define WATCHDOG_TIMEOUT 2000 /* 20 sec */
+#define WATCHDOG_TIMEOUT 20*HZ /* 20 sec */
X
-typedef void (*TIMER_CALLBACK)( unsigned long);
+typedef void (*TIMER_CALLBACK)(unsigned long);
X
-void irda_start_timer( struct timer_list *ptimer, int timeout, int data,
- TIMER_CALLBACK callback);
+void irda_start_timer(struct timer_list *ptimer, int timeout, int data,
+ TIMER_CALLBACK callback);
X
-inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout);
-inline void irlap_start_query_timer( struct irlap_cb *self, int timeout);
-inline void irlap_start_final_timer( struct irlap_cb *self, int timeout);
-inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout);
-inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout);
+inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
+inline void irlap_start_query_timer(struct irlap_cb *self, int timeout);
+inline void irlap_start_final_timer(struct irlap_cb *self, int timeout);
+inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
+inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
X
-inline void irda_device_start_mbusy_timer( struct irda_device *self);
+inline void irda_device_start_mbusy_timer(struct irda_device *self);
X
X struct lsap_cb;
X struct lap_cb;
-inline void irlmp_start_watchdog_timer( struct lsap_cb *, int timeout);
-inline void irlmp_start_discovery_timer( struct irlmp_cb *, int timeout);
+inline void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout);
+inline void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout);
X inline void irlmp_start_idle_timer(struct lap_cb *, int timeout);
X
X struct irobex_cb;
-inline void irobex_start_watchdog_timer( struct irobex_cb *, int timeout);
+inline void irobex_start_watchdog_timer(struct irobex_cb *, int timeout);
X
X #endif
X
diff -u --recursive --new-file v2.2.5/linux/include/net/irda/uircc.h linux/include/net/irda/uircc.h
--- v2.2.5/linux/include/net/irda/uircc.h Wed Jan 20 23:14:06 1999
+++ linux/include/net/irda/uircc.h Thu Apr 15 05:42:42 1999
@@ -7,7 +7,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sat Dec 26 11:00:49 1998
- * Modified at: Tue Jan 19 23:52:46 1999
+ * Modified at: Thu Mar 11 01:37:20 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -77,6 +77,7 @@
X
X #define UIRCC_CR12 0x0c /* Timer counter initial value (low byte) */
X #define UIRCC_CR13 0x0d /* Timer counter initial value (high byte) */
+#define UIRCC_CR15 0x0f
X
X /* Status registers (read only) */
X #define UIRCC_SR0 0x00 /* Transmit/receive status register */
@@ -102,9 +103,10 @@
X #define UIRCC_SR9 0x09 /* System status 1 */
X
X #define UIRCC_SR10 0x0a /* Modem select status */
-
+#define UIRCC_SR11 0x0b
X #define UIRCC_SR12 0x0c /* Timer counter status (low byte) */
X #define UIRCC_SR13 0x0d /* Timer counter status (high byte) */
+#define UIRCC_SR15 0x0f
X
X /* Private data for each instance */
X struct uircc_cb {
diff -u --recursive --new-file v2.2.5/linux/include/net/sock.h linux/include/net/sock.h
--- v2.2.5/linux/include/net/sock.h Mon Mar 29 11:09:12 1999
+++ linux/include/net/sock.h Fri Apr 16 14:29:08 1999
@@ -81,6 +81,10 @@
X #include <net/dn.h>
X #endif
X
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
+#include <net/irda/irda.h>
+#endif
+
X #ifdef CONFIG_FILTER
X #include <linux/filter.h>
X #endif
@@ -490,6 +494,9 @@
X #endif
X #if defined(CONFIG_ECONET) || defined(CONFIG_ECONET_MODULE)
X struct econet_opt *af_econet;
+#endif
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
+ struct irda_sock *irda;
X #endif
X } protinfo;
X
diff -u --recursive --new-file v2.2.5/linux/include/scsi/sg.h linux/include/scsi/sg.h
--- v2.2.5/linux/include/scsi/sg.h Tue Apr 14 14:29:26 1998
+++ linux/include/scsi/sg.h Fri Apr 16 11:59:28 1999
@@ -1,34 +1,157 @@
+#ifndef _SCSI_GENERIC_H
+#define _SCSI_GENERIC_H
+
X /*
X History:
X Started: Aug 9 by Lawrence Foard (ent...@world.std.com), to allow user
- process control of SCSI devices.
+ process control of SCSI devices.
X Development Sponsored by Killy Corp. NY NY
-*/
-
-#ifndef _SCSI_GENERIC_H
-#define _SCSI_GENERIC_H
+Original driver (sg.h):
+* Copyright (C) 1992 Lawrence Foard
+2.x extensions to driver:
+* Copyright (C) 1998, 1999 Douglas Gilbert
+
+
+ Version: 2.1.31 (990327)
+ This version for later 2.1.x series and 2.2.x kernels
+ D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au)
+
+ Changes since 2.1.30 (990320)
+ - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
+ - increase max allowable mid-level pool usage
+ Changes since 2.1.21 (990315)
+ - skipped to 2.1.30 indicating interface change (revert to 2.1.9)
+ - remove attempt to accomodate cdrecord 1.8, will fix app
+ - keep SG_?ET_RESERVED_SIZE naming for clarity
+ Changes since 2.1.20 (990313)
+ - ommission: left out logic for SG_?ET_ALT_INTERFACE, now added
+ Changes since 2.1.9 (990309)
+ - skipped to version 2.1.20 to indicate some interface changes
+ - incorporate sg changes to make cdrecord 1.8 work (had its
+ own patches that were different from the original)
+ - change SG_?ET_BUFF_SIZE to SG_?ET_RESERVED_SIZE for clarity
+ Changes since 2.1.8 (990303)
+ - debug ">9" option dumps debug for _all_ active sg devices
+ - increase allowable dma pool usage + increase minimum threshhold
+ - pad out sg_scsi_id structure
+ Changes since 2.1.7 (990227)
+ - command queuing now "non-default" [back. compat. with cdparanoia]
+ - Tighten access on some ioctls
+
+
+ New features and changes:
+ - per file descriptor (fd) write-read sequencing and command queues.
+ - command queuing supported (SG_MAX_QUEUE is maximum per fd).
+ - scatter-gather supported (allowing potentially megabyte transfers).
+ - the SCSI target, host and driver status are returned
+ in unused fields of sg_header (maintaining its original size).
+ - asynchronous notification support added (SIGPOLL, SIGIO) for
+ read()s ( write()s should never block).
+ - pack_id logic added so read() can be made to wait for a specific
+ pack_id.
+ - uses memory > ISA_DMA_THRESHOLD if adapter allows it (e.g. a
+ pci scsi adapter).
+ - this driver no longer uses a single SG_BIG_BUFF sized buffer
+ obtained at driver/module init time. Rather it obtains a
+ SG_SCATTER_SZ buffer when a fd is open()ed and frees it at
+ the corresponding release() (ie pr fd). Hence open() can return
+ ENOMEM! If write() request > SG_SCATTER_SZ bytes for data then
+ it can fail with ENOMEM as well (if so, scale back).
+ - adds several ioctl calls, see ioctl section below.
+ - SG_SCATTER_SZ's presence indicates this version of "sg" driver.
+
+ Good documentation on the original "sg" device interface and usage can be
+ found in the Linux HOWTO document: "SCSI Programming HOWTO" by Heiko
+ Eissfeldt; last updated 7 May 1996. I will add more info on using the
+ extensions in this driver as required. A quick summary:
+ An SG device is accessed by writing SCSI commands plus any associated
+ outgoing data to it; the resulting status codes and any incoming data
+ are then obtained by a read call. The device can be opened O_NONBLOCK
+ (non-blocking) and poll() used to monitor its progress. The device may be
+ opened O_EXCL which excludes other "sg" users from this device (but not
+ "sd", "st" or "sr" users). The buffer given to the write() call is made
+ up as follows:
+ - struct sg_header image (see below)
+ - scsi command (6, 10 or 12 bytes long)
+ - data to be written to the device (if any)
+
+ The buffer received from the corresponding read() call contains:
+ - struct sg_header image (check results + sense_buffer)
+ - data read back from device (if any)
+
+ The given SCSI command has its LUN field overwritten internally by the
+ value associated with the device that has been opened.
+
+ Memory (RAM) is used within this driver for direct memory access (DMA)
+ in transferring data to and from the SCSI device. The dreaded ENOMEM
+ seems to be more prevalent under early 2.2.x kernels than under the
+ 2.0.x kernel series. For a given (large) transfer the memory obtained by
+ this driver must be contiguous or scatter-gather must be used (if
+ supported by the adapter). [Furthermore, ISA SCSI adapters can only use
+ memory below the 16MB level on a i386.]
+ This driver tries hard to find some suitable memory before admitting
+ defeat and returning ENOMEM. All is not lost if application writers
+ then back off the amount they are requesting. The value returned by
+ the SG_GET_RESERVED_SIZE ioctl is guaranteed to be available (one
+ per fd). This driver does the following:
+ - attempts to reserve a SG_SCATTER_SZ sized buffer on open(). The
+ actual amount reserved is given by the SG_GET_RESERVED_SIZE ioctl().
+ - each write() needs to reserve a DMA buffer of the size of the
+ data buffer indicated (excluding sg_header and command overhead).
+ This buffer, depending on its size, adapter type (ISA or not) and
+ the amount of memory available will be obtained from the kernel
+ directly (get_free_pages or kmalloc) or the from the scsi mid-level
+ dma pool (taking care not to exhaust it).
+ If the buffer requested is > SG_SCATTER_SZ or memory is tight then
+ scatter-gather will be used if supported by the adapter.
+ - write() will also attempt to use the buffer reserved on open()
+ if it is large enough.
+ The above strategy ensures that a write() can always depend on a buffer
+ of the size indicated by the SG_GET_RESERVED_SIZE ioctl() (which could be
+ 0, but at least the app knows things are tight in advance).
+ Hence application writers can adopt quite aggressive strategies (e.g.
+ requesting 512KB) and scale them back in the face of ENOMEM errors.
+ N.B. Queuing up commands also ties up kernel memory.
X
-/*
- An SG device is accessed by writing "packets" to it, the replies
- are then read using the read call. The same header is used for
- reply, just ignore reply_len field.
+ More documentation can be found at www.netwinder.org/~dougg
X */
X
+#define SG_MAX_SENSE 16 /* too little, unlikely to change in 2.2.x */
+
X struct sg_header
- {
- int pack_len; /* length of incoming packet <4096 (including header) */
- int reply_len; /* maximum length <4096 of expected reply */
- int pack_id; /* id number of packet */
- int result; /* 0==ok, otherwise refer to errno codes */
- unsigned int twelve_byte:1; /* Force 12 byte command length for group 6 & 7 commands */
- unsigned int other_flags:31; /* for future use */
- unsigned char sense_buffer[16]; /* used only by reads */
- /* command follows then data for command */
- };
-
-/* ioctl's */
-#define SG_SET_TIMEOUT 0x2201 /* set timeout *(int *)arg==timeout */
-#define SG_GET_TIMEOUT 0x2202 /* get timeout return timeout */
+{
+ int pack_len; /* [o] reply_len (ie useless), ignored as input */
+ int reply_len; /* [i] max length of expected reply (inc. sg_header) */
+ int pack_id; /* [io] id number of packet (use ints >= 0) */
+ int result; /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */
+ unsigned int twelve_byte:1;
+ /* [i] Force 12 byte command length for group 6 & 7 commands */
+ unsigned int target_status:5; /* [o] scsi status from target */
+ unsigned int host_status:8; /* [o] host status (see "DID" codes) */
+ unsigned int driver_status:8; /* [o] driver status+suggestion */
+ unsigned int other_flags:10; /* unused */
+ unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
+ when target_status is CHECK_CONDITION or
+ when target_status is COMMAND_TERMINATED or
+ when (driver_status & DRIVER_SENSE) is true. */
+}; /* This structure is 36 bytes long on i386 */
+
+
+typedef struct sg_scsi_id {
+ int host_no; /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
+ int channel;
+ int scsi_id; /* scsi id of target device */
+ int lun;
+ int scsi_type; /* TYPE_... defined in scsi/scsi.h */
+ int unused1; /* probably find a good use, set 0 for now */
+ int unused2; /* ditto */
+ int unused3;
+} Sg_scsi_id;
+
+/* ioctls ( _GET_s yield result via 'int *' 3rd argument unless
+ otherwise indicated */
+#define SG_SET_TIMEOUT 0x2201 /* unit: jiffies, 10ms on i386 */
+#define SG_GET_TIMEOUT 0x2202 /* yield timeout as _return_ value */
X
X #define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */
X
@@ -36,12 +159,66 @@
X #define SG_SET_TRANSFORM 0x2204
X #define SG_GET_TRANSFORM 0x2205
X
-#define SG_DEFAULT_TIMEOUT (60*HZ) /* 1 minute timeout */
+#define SG_SET_RESERVED_SIZE 0x2275 /* currently ignored, future addition */
+/* Following yields buffer reserved by open(): 0 <= x <= SG_SCATTER_SZ */
+#define SG_GET_RESERVED_SIZE 0x2272
+
+/* The following ioctl takes a 'Sg_scsi_id *' object as its 3rd argument. */
+#define SG_GET_SCSI_ID 0x2276 /* Yields fd's bus,chan,dev,lun+type */
+/* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */
+
+/* Override adapter setting and always DMA using low memory ( <16MB on i386).
+ Default is 0 (off - use adapter setting) */
+#define SG_SET_FORCE_LOW_DMA 0x2279 /* 0-> use adapter setting, 1-> force */
+#define SG_GET_LOW_DMA 0x227a /* 0-> use all ram for dma; 1-> low dma ram */
+
+/* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which
+ will attempt to read that pack_id or block (or return EAGAIN). If
+ pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
+ (default) then pack_id ignored by read() and oldest readable fetched. */
+#define SG_SET_FORCE_PACK_ID 0x227b
+#define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */
+
+#define SG_GET_NUM_WAITING 0x227d /* Number of commands awaiting read() */
+
+/* Turn on error sense trace (1..8), dump this device to log/console (9)
+ or dump all sg device states ( >9 ) to log/console */
+#define SG_SET_DEBUG 0x227e /* 0 -> turn off debug */
+
+/* Yields max scatter gather tablesize allowed by current host adapter */
+#define SG_GET_SG_TABLESIZE 0x227F /* 0 implies can't do scatter gather */
+
+/* Control whether sequencing per file descriptor (default) or per device */
+#define SG_GET_MERGE_FD 0x2274 /* 0-> per fd (default), 1-> per device */
+#define SG_SET_MERGE_FD 0x2273 /* Attempt to change sequencing state,
+ if more than 1 fd open on device, will fail with EBUSY */
+
+/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q) */
+#define SG_GET_COMMAND_Q 0x2270 /* Yields 0 (queuing off) or 1 (on) */
+#define SG_SET_COMMAND_Q 0x2271 /* Change queuing state with 0 or 1 */
+
+
+#define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
X #define SG_DEFAULT_RETRIES 1
X
-#define SG_MAX_QUEUE 4 /* maximum outstanding request, arbitrary, may be
- changed if sufficient DMA buffer room available */
+/* Default modes, commented if they differ from original sg driver */
+#define SG_DEF_COMMAND_Q 0
+#define SG_DEF_MERGE_FD 0 /* was 1 -> per device sequencing */
+#define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */
+#define SG_DEF_FORCE_PACK_ID 0
+
+/* maximum outstanding requests, write() yields EDOM if exceeded */
+#define SG_MAX_QUEUE 16
+
+#define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */
+/* Largest size (in bytes) a single scatter-gather list element can have.
+ The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
+ i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
+ by adapter then this value is the largest data block that can be
+ read/written by a single scsi command. Max number of scatter-gather
+ list elements seems to be limited to 255. */
X
-#define SG_BIG_BUFF 32768
+#define SG_BIG_BUFF SG_SCATTER_SZ /* for backward compatibility */
+/* #define SG_BIG_BUFF (SG_SCATTER_SZ * 8) */ /* =256KB, if you want */
X
X #endif
diff -u --recursive --new-file v2.2.5/linux/init/main.c linux/init/main.c
--- v2.2.5/linux/init/main.c Wed Mar 10 15:29:50 1999
+++ linux/init/main.c Mon Apr 12 09:51:03 1999
@@ -179,6 +179,7 @@
X extern void AM53C974_setup(char *str, int *ints);
X extern void BusLogic_Setup(char *str, int *ints);
X extern void ncr53c8xx_setup(char *str, int *ints);
+extern void sym53c8xx_setup(char *str, int *ints);
X extern void eata2x_setup(char *str, int *ints);
X extern void u14_34f_setup(char *str, int *ints);
X extern void fdomain_setup(char *str, int *ints);
@@ -677,6 +678,9 @@
X #endif
X #ifdef CONFIG_SCSI_NCR53C8XX
X { "ncr53c8xx=", ncr53c8xx_setup},
+#endif
+#ifdef CONFIG_SCSI_SYM53C8XX
+ { "sym53c8xx=", sym53c8xx_setup},
X #endif
X #ifdef CONFIG_SCSI_EATA
X { "eata=", eata2x_setup},
diff -u --recursive --new-file v2.2.5/linux/ipc/shm.c linux/ipc/shm.c
--- v2.2.5/linux/ipc/shm.c Thu Dec 31 10:29:03 1998
+++ linux/ipc/shm.c Mon Apr 12 14:27:26 1999
@@ -24,7 +24,8 @@
X static void killseg (int id);
X static void shm_open (struct vm_area_struct *shmd);
X static void shm_close (struct vm_area_struct *shmd);
-static pte_t shm_swap_in(struct vm_area_struct *, unsigned long, unsigned long);
+static unsigned long shm_nopage(struct vm_area_struct *, unsigned long, int);
+static int shm_swapout(struct vm_area_struct *, struct page *);
X
X static int shm_tot = 0; /* total number of shared memory pages */
X static int shm_rss = 0; /* number of shared memory pages that are in memory */
@@ -364,10 +365,10 @@
X NULL, /* protect */
X NULL, /* sync */
X NULL, /* advise */
- NULL, /* nopage (done with swapin) */
+ shm_nopage, /* nopage */
X NULL, /* wppage */
- NULL, /* swapout (hardcoded right now) */
- shm_swap_in /* swapin */
+ shm_swapout, /* swapout */
+ NULL /* swapin */
X };
X
X /* Insert shmd into the list shp->attaches */
@@ -393,11 +394,7 @@
X */
X static int shm_map (struct vm_area_struct *shmd)
X {
- pgd_t *page_dir;
- pmd_t *page_middle;
- pte_t *page_table;
- unsigned long tmp, shm_sgn;
- int error;
+ unsigned long tmp;
X
X /* clear old mappings */
X do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start);
@@ -411,30 +408,7 @@
X insert_vm_struct(current->mm, shmd);
X merge_segments(current->mm, shmd->vm_start, shmd->vm_end);
X
- /* map page range */
- error = 0;
- shm_sgn = shmd->vm_pte +
- SWP_ENTRY(0, (shmd->vm_offset >> PAGE_SHIFT) << SHM_IDX_SHIFT);
- flush_cache_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
- for (tmp = shmd->vm_start;
- tmp < shmd->vm_end;
- tmp += PAGE_SIZE, shm_sgn += SWP_ENTRY(0, 1 << SHM_IDX_SHIFT))
- {
- page_dir = pgd_offset(shmd->vm_mm,tmp);
- page_middle = pmd_alloc(page_dir,tmp);
- if (!page_middle) {
- error = -ENOMEM;
- break;
- }
- page_table = pte_alloc(page_middle,tmp);
- if (!page_table) {
- error = -ENOMEM;
- break;
- }
- set_pte(page_table, __pte(shm_sgn));
- }
- flush_tlb_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
- return error;


+ return 0;
X }
X
X /*

@@ -615,44 +589,46 @@
X }
X
X /*
+ * Enter the shm page into the SHM data structures.
+ *
+ * The way "nopage" is done, we don't actually have to
+ * do anything here: nopage will have filled in the shm
+ * data structures already, and shm_swap_out() will just
+ * work off them..
+ */
+static int shm_swapout(struct vm_area_struct * vma, struct page * page)


+{
+ return 0;
+}
+

+/*
X * page not present ... go through shm_pages
X */
-static pte_t shm_swap_in(struct vm_area_struct * shmd, unsigned long offset, unsigned long code)
+static unsigned long shm_nopage(struct vm_area_struct * shmd, unsigned long address, int no_share)
X {
X pte_t pte;
X struct shmid_kernel *shp;
X unsigned int id, idx;
X
- id = SWP_OFFSET(code) & SHM_ID_MASK;
+ id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK;
+ idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT;
+
X #ifdef DEBUG_SHM
- if (id != (SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK)) {
- printk ("shm_swap_in: code id = %d and shmd id = %ld differ\n",
- id, SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK);
- return BAD_PAGE;
- }
X if (id > max_shmid) {
- printk ("shm_swap_in: id=%d too big. proc mem corrupted\n", id);
- return BAD_PAGE;
+ printk ("shm_nopage: id=%d too big. proc mem corrupted\n", id);
+ return 0;
X }
X #endif
X shp = shm_segs[id];
X
X #ifdef DEBUG_SHM
X if (shp == IPC_UNUSED || shp == IPC_NOID) {
- printk ("shm_swap_in: id=%d invalid. Race.\n", id);
- return BAD_PAGE;
- }
-#endif
- idx = (SWP_OFFSET(code) >> SHM_IDX_SHIFT) & SHM_IDX_MASK;
-#ifdef DEBUG_SHM
- if (idx != (offset >> PAGE_SHIFT)) {
- printk ("shm_swap_in: code idx = %u and shmd idx = %lu differ\n",
- idx, offset >> PAGE_SHIFT);
- return BAD_PAGE;
+ printk ("shm_nopage: id=%d invalid. Race.\n", id);
+ return 0;
X }
X if (idx >= shp->shm_npages) {
- printk ("shm_swap_in : too large page index. id=%d\n", id);
- return BAD_PAGE;
+ printk ("shm_nopage : too large page index. id=%d\n", id);
+ return 0;
X }
X #endif
X
@@ -661,7 +637,7 @@
X unsigned long page = get_free_page(GFP_KERNEL);
X if (!page) {
X oom(current);
- return BAD_PAGE;
+ return 0;
X }
X pte = __pte(shp->shm_pages[idx]);
X if (pte_present(pte)) {
@@ -687,7 +663,7 @@
X done: /* pte_val(pte) == shp->shm_pages[idx] */
X current->min_flt++;
X atomic_inc(&mem_map[MAP_NR(pte_page(pte))].count);
- return pte_modify(pte, shmd->vm_page_prot);
+ return pte_page(pte);
X }
X
X /*
@@ -700,7 +676,6 @@
X {
X pte_t page;
X struct shmid_kernel *shp;
- struct vm_area_struct *shmd;
X unsigned long swap_nr;
X unsigned long id, idx;
X int loop = 0;
@@ -742,61 +717,6 @@
X swap_free (swap_nr);
X return 0;
X }
- if (shp->attaches)
- for (shmd = shp->attaches; ; ) {
- do {
- pgd_t *page_dir;
- pmd_t *page_middle;
- pte_t *page_table, pte;
- unsigned long tmp;
-
- if ((SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK) != id) {
- printk ("shm_swap: id=%ld does not match shmd->vm_pte.id=%ld\n",
- id, SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK);
- continue;
- }
- tmp = shmd->vm_start + (idx << PAGE_SHIFT) - shmd->vm_offset;
- if (!(tmp >= shmd->vm_start && tmp < shmd->vm_end))
- continue;
- page_dir = pgd_offset(shmd->vm_mm,tmp);
- if (pgd_none(*page_dir) || pgd_bad(*page_dir)) {
- printk("shm_swap: bad pgtbl! id=%ld start=%lx idx=%ld\n",
- id, shmd->vm_start, idx);
- pgd_clear(page_dir);
- continue;
- }
- page_middle = pmd_offset(page_dir,tmp);
- if (pmd_none(*page_middle) || pmd_bad(*page_middle)) {
- printk("shm_swap: bad pgmid! id=%ld start=%lx idx=%ld\n",
- id, shmd->vm_start, idx);
- pmd_clear(page_middle);
- continue;
- }
- page_table = pte_offset(page_middle,tmp);
- pte = *page_table;
- if (!pte_present(pte))
- continue;
- if (pte_young(pte)) {
- set_pte(page_table, pte_mkold(pte));
- continue;
- }
- if (pte_page(pte) != pte_page(page))
- printk("shm_swap_out: page and pte mismatch %lx %lx\n",
- pte_page(pte),pte_page(page));
- flush_cache_page(shmd, tmp);
- set_pte(page_table,
- __pte(shmd->vm_pte + SWP_ENTRY(0, idx << SHM_IDX_SHIFT)));
- atomic_dec(&mem_map[MAP_NR(pte_page(pte))].count);
- if (shmd->vm_mm->rss > 0)
- shmd->vm_mm->rss--;
- flush_tlb_page(shmd, tmp);
- /* continue looping through the linked list */
- } while (0);
- shmd = shmd->vm_next_share;
- if (!shmd)
- break;
- }
-
X if (atomic_read(&mem_map[MAP_NR(pte_page(page))].count) != 1)
X goto check_table;
X shp->shm_pages[idx] = swap_nr;
diff -u --recursive --new-file v2.2.5/linux/kernel/fork.c linux/kernel/fork.c
--- v2.2.5/linux/kernel/fork.c Mon Mar 29 11:09:12 1999
+++ linux/kernel/fork.c Mon Apr 12 12:44:26 1999
@@ -93,6 +93,18 @@
X return up;
X }
X
+/*
+ * For SMP, we need to re-test the user struct counter
+ * after having aquired the spinlock. This allows us to do
+ * the common case (not freeing anything) without having
+ * any locking.
+ */
+#ifdef __SMP__
+ #define uid_hash_free(up) (!atomic_read(&(up)->count))
+#else
+ #define uid_hash_free(up) (1)
+#endif
+
X void free_uid(struct task_struct *p)
X {
X struct user_struct *up = p->user;
@@ -101,9 +113,11 @@
X p->user = NULL;
X if (atomic_dec_and_test(&up->count)) {
X spin_lock(&uidhash_lock);
- uid_hash_remove(up);
+ if (uid_hash_free(up)) {
+ uid_hash_remove(up);
+ kmem_cache_free(uid_cachep, up);
+ }
X spin_unlock(&uidhash_lock);
- kmem_cache_free(uid_cachep, up);
X }
X }
X }
diff -u --recursive --new-file v2.2.5/linux/mm/memory.c linux/mm/memory.c
--- v2.2.5/linux/mm/memory.c Tue Jan 19 11:32:53 1999
+++ linux/mm/memory.c Mon Apr 12 16:18:26 1999
@@ -585,7 +585,8 @@
X return 0;
X }
X if (!pte_none(*pte)) {
- printk("put_dirty_page: page already exists\n");
+ printk("put_dirty_page: pte %08lx already exists\n",
+ pte_val(*pte));


X free_page(page);
X return 0;

X }
diff -u --recursive --new-file v2.2.5/linux/mm/mmap.c linux/mm/mmap.c
--- v2.2.5/linux/mm/mmap.c Wed Mar 10 15:29:50 1999
+++ linux/mm/mmap.c Mon Apr 12 21:35:15 1999
@@ -490,8 +490,8 @@
X * allocate a new one, and the return indicates whether the old
X * area was reused.
X */
-static int unmap_fixup(struct vm_area_struct *area, unsigned long addr,
- size_t len, struct vm_area_struct **extra)
+static struct vm_area_struct * unmap_fixup(struct vm_area_struct *area,
+ unsigned long addr, size_t len, struct vm_area_struct *extra)
X {
X struct vm_area_struct *mpnt;
X unsigned long end = addr + len;
@@ -506,7 +506,8 @@
X area->vm_ops->close(area);
X if (area->vm_file)
X fput(area->vm_file);
- return 0;
+ kmem_cache_free(vm_area_cachep, area);
+ return extra;
X }
X
X /* Work out to one of the ends. */
@@ -518,8 +519,8 @@
X } else {
X /* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */
X /* Add end mapping -- leave beginning for below */
- mpnt = *extra;
- *extra = NULL;
+ mpnt = extra;
+ extra = NULL;
X
X mpnt->vm_mm = area->vm_mm;
X mpnt->vm_start = end;
@@ -539,7 +540,7 @@
X }
X
X insert_vm_struct(current->mm, area);
- return 1;
+ return extra;
X }
X
X /*
@@ -566,8 +567,8 @@
X if (!prev)
X goto no_mmaps;
X if (prev->vm_end > start) {
- if (last > prev->vm_end)
- last = prev->vm_end;
+ if (last > prev->vm_start)
+ last = prev->vm_start;
X goto no_mmaps;
X }
X }
@@ -674,8 +675,7 @@
X /*
X * Fix the mapping, and free the old area if it wasn't reused.
X */
- if (!unmap_fixup(mpnt, st, size, &extra))
- kmem_cache_free(vm_area_cachep, mpnt);
+ extra = unmap_fixup(mpnt, st, size, extra);
X }
X
X /* Release the extra vma struct if it wasn't used */
diff -u --recursive --new-file v2.2.5/linux/net/README linux/net/README
--- v2.2.5/linux/net/README Sun Jun 7 11:16:40 1998
+++ linux/net/README Mon Apr 12 16:18:27 1999
@@ -16,7 +16,7 @@
X lapb g4...@g4klx.demon.co.uk
X netrom g4...@g4klx.demon.co.uk
X rose g4...@g4klx.demon.co.uk
-wanrouter ge...@compuserve.com and d...@sangoma.com
+wanrouter ge...@compuserve.com, jaspreet@sangoma and d...@sangoma.com
X unix al...@lxorguk.ukuu.org.uk
X x25 g4...@g4klx.demon.co.uk
X
diff -u --recursive --new-file v2.2.5/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v2.2.5/linux/net/appletalk/aarp.c Mon Dec 28 15:00:53 1998
+++ linux/net/appletalk/aarp.c Mon Apr 12 16:18:26 1999
@@ -128,6 +128,8 @@
X
X skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
X eah = (struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
+ skb->protocol = htons(ETH_P_ATALK);
+ skb->nh.raw = skb->h.raw = (void *) eah;
X skb->dev = dev;
X
X /*
@@ -186,6 +188,8 @@
X
X skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
X eah = (struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
+ skb->protocol = htons(ETH_P_ATALK);
+ skb->nh.raw = skb->h.raw = (void *) eah;
X skb->dev = dev;
X
X /*
@@ -246,7 +250,8 @@
X
X skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
X eah = (struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
-
+ skb->protocol = htons(ETH_P_ATALK);
+ skb->nh.raw = skb->h.raw = (void *) eah;
X skb->dev = dev;
X
X /*
@@ -365,12 +370,10 @@
X aarp_expire_timer(&unresolved[ct]);
X aarp_expire_timer(&proxies[ct]);
X }
- del_timer(&aarp_timer);
- if(unresolved_count==0)
- aarp_timer.expires=jiffies+sysctl_aarp_expiry_time;
- else
- aarp_timer.expires=jiffies+sysctl_aarp_tick_time;
- add_timer(&aarp_timer);
+
+ mod_timer(&aarp_timer, jiffies +
+ (unresolved_count ? sysctl_aarp_tick_time:
+ sysctl_aarp_expiry_time));
X }
X
X /*
@@ -750,9 +753,7 @@
X
X if(unresolved_count==1)
X {
- del_timer(&aarp_timer);
- aarp_timer.expires=jiffies+sysctl_aarp_tick_time;
- add_timer(&aarp_timer);
+ mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time);
X }
X
X /*
@@ -939,9 +940,8 @@
X aarp_resolved(&unresolved[hash],a,hash);
X if(unresolved_count==0)
X {
- del_timer(&aarp_timer);
- aarp_timer.expires=jiffies+sysctl_aarp_expiry_time;
- add_timer(&aarp_timer);
+ mod_timer(&aarp_timer, jiffies +
+ sysctl_aarp_expiry_time);
X }
X break;
X
diff -u --recursive --new-file v2.2.5/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.2.5/linux/net/ipv6/tcp_ipv6.c Mon Mar 29 11:09:12 1999
+++ linux/net/ipv6/tcp_ipv6.c Fri Apr 16 08:20:23 1999
@@ -18,6 +18,7 @@
X * 2 of the License, or (at your option) any later version.


X */
X
+#include <linux/config.h>

X #include <linux/errno.h>
X #include <linux/types.h>
X #include <linux/socket.h>
diff -u --recursive --new-file v2.2.5/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.2.5/linux/net/irda/Config.in Wed Jan 20 23:14:07 1999
+++ linux/net/irda/Config.in Thu Apr 15 05:42:42 1999
@@ -12,7 +12,6 @@
X if [ "$CONFIG_IRDA" != "n" ] ; then
X comment 'IrDA protocols'
X source net/irda/irlan/Config.in
- source net/irda/irobex/Config.in
X source net/irda/ircomm/Config.in
X source net/irda/irlpt/Config.in
X
@@ -21,7 +20,6 @@
X comment ' IrDA options'
X bool ' Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
X bool ' Fast RRs' CONFIG_IRDA_FAST_RR
- bool ' Recycle RRs' CONFIG_IRDA_RECYCLE_RR
X bool ' Debug information' CONFIG_IRDA_DEBUG
X fi
X fi
diff -u --recursive --new-file v2.2.5/linux/net/irda/Makefile linux/net/irda/Makefile
--- v2.2.5/linux/net/irda/Makefile Wed Mar 10 15:29:52 1999
+++ linux/net/irda/Makefile Thu Apr 15 05:42:42 1999
@@ -15,7 +15,8 @@
X O_TARGET := irda.o
X O_OBJS := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
X irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
- irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o
+ irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o \
+ discovery.o
X OX_OBJS := irmod.o
X
X MOD_LIST_NAME := IRDA_MODULES
@@ -51,15 +52,6 @@
X else
X ifeq ($(CONFIG_IRLPT),m)
X MOD_IN_SUB_DIRS += irlpt
- endif
-endif
-
-ifeq ($(CONFIG_IROBEX),y)
-SUB_DIRS += irobex
-O_OBJS += irobex/irobex.o
-else
- ifeq ($(CONFIG_IROBEX),m)
- MOD_SUB_DIRS += irobex
X endif
X endif
X
diff -u --recursive --new-file v2.2.5/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.2.5/linux/net/irda/af_irda.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/af_irda.c Fri Apr 16 08:20:23 1999
@@ -1,16 +1,16 @@
X /*********************************************************************
X *
X * Filename: af_irda.c
- * Version: 0.1
+ * Version: 0.6
X * Description: IrDA sockets implementation
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sun May 31 10:12:43 1998
- * Modified at: Sat Feb 20 01:31:15 1999
+ * Modified at: Wed Apr 7 17:32:27 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
- * Sources: af_netroom.c, af_ax25.x
+ * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
X *
- * Copyright (c) 1997 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.


X *
X * This program is free software; you can redistribute it and/or

X * modify it under the terms of the GNU General Public License as
@@ -23,44 +23,365 @@
X *
X ********************************************************************/
X
-#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/socket.h>
X #include <linux/sockios.h>
X #include <linux/init.h>
X #include <linux/if_arp.h>
X #include <linux/net.h>
+#include <linux/irda.h>
X
X #include <asm/uaccess.h>
X
X #include <net/sock.h>
X
X #include <net/irda/irda.h>
-#include <net/irda/irmod.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irias_object.h>
X #include <net/irda/irttp.h>
X
-extern int irda_init(void);
+extern int irda_init(void);
X extern void irda_cleanup(void);
-extern int irlap_input(struct sk_buff *, struct device *, struct packet_type *);
+extern int irlap_driver_rcv(struct sk_buff *, struct device *,
+ struct packet_type *);
X
X static struct proto_ops irda_proto_ops;
+static hashbin_t *cachelog = NULL;
+static struct wait_queue *discovery_wait; /* Wait for discovery */
X
X #define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
X
-#define IRDA_SOCKETS
+/*
+ * Function irda_data_indication (instance, sap, skb)
+ *
+ * Received some data from TinyTP. Just queue it on the receive queue
+ *
+ */
+static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb)
+{
+ struct irda_sock *self;
+ struct sock *sk;
+ int err;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = (struct irda_sock *) instance;
+ ASSERT(self != NULL, return -1;);
+
+ sk = self->sk;
+ ASSERT(sk != NULL, return -1;);
+
+ err = sock_queue_rcv_skb(sk, skb);
+ if (err) {
+ DEBUG(1, __FUNCTION__ "(), error: no more mem!\n");
+ self->rx_flow = FLOW_STOP;
+
+ /* When we return error, TTP will need to requeue the skb */
+ return err;
+ }


+
+ return 0;
+}
+

+/*
+ * Function irda_disconnect_indication (instance, sap, reason, skb)
+ *
+ * Connection has been closed. Chech reason to find out why
+ *
+ */
+static void irda_disconnect_indication(void *instance, void *sap,
+ LM_REASON reason, struct sk_buff *skb)
+{
+ struct irda_sock *self;
+ struct sock *sk;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = (struct irda_sock *) instance;
+
+ sk = self->sk;
+ if (sk == NULL)
+ return;
+
+ sk->state = TCP_CLOSE;
+ sk->err = reason;
+ sk->shutdown |= SEND_SHUTDOWN;
+ if (!sk->dead) {
+ sk->state_change(sk);
+ sk->dead = 1;
+ }
+}
+
+/*
+ * Function irda_connect_confirm (instance, sap, qos, max_sdu_size, skb)
+ *
+ * Connections has been confirmed by the remote device
+ *
+ */
+static void irda_connect_confirm(void *instance, void *sap,
+ struct qos_info *qos,
+ __u32 max_sdu_size, struct sk_buff *skb)
+{
+ struct irda_sock *self;
+ struct sock *sk;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = (struct irda_sock *) instance;
+
+ self->max_sdu_size_tx = max_sdu_size;
+ memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
+
+ sk = self->sk;
+ if (sk == NULL)
+ return;
+
+ /* We are now connected! */
+ sk->state = TCP_ESTABLISHED;
+ sk->state_change(sk);
+}
+
+/*
+ * Function irda_connect_indication(instance, sap, qos, max_sdu_size, userdata)
+ *
+ * Incomming connection
+ *
+ */
+static void irda_connect_indication(void *instance, void *sap,
+ struct qos_info *qos, __u32 max_sdu_size,
+ struct sk_buff *skb)
+{
+ struct irda_sock *self;
+ struct sock *sk;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = (struct irda_sock *) instance;
+
+ self->max_sdu_size_tx = max_sdu_size;
+ memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
+
+ sk = self->sk;
+ if (sk == NULL)
+ return;
+
+ skb_queue_tail(&sk->receive_queue, skb);
+
+ sk->state_change(sk);
+}
+
+/*
+ * Function irda_connect_response (handle)
+ *
+ * Accept incomming connection
+ *
+ */
+void irda_connect_response(struct irda_sock *self)
+{
+ struct sk_buff *skb;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return;);
+
+ skb = dev_alloc_skb(64);
+ if (skb == NULL) {
+ DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n");
+ return;
+ }
+
+ /* Reserve space for MUX_CONTROL and LAP header */
+ skb_reserve(skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER);
+
+ irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);
+}
+
+
+/*
+ * Function irda_flow_indication (instance, sap, flow)
+ *
+ * Used by TinyTP to tell us if it can accept more data or not
+ *
+ */
+static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+{
+ struct irda_sock *self;
+ struct sock *sk;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = (struct irda_sock *) instance;
+ ASSERT(self != NULL, return;);
+
+ sk = self->sk;
+ ASSERT(sk != NULL, return;);
+
+ switch (flow) {
+ case FLOW_STOP:
+ DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n");
+ self->tx_flow = flow;
+ break;
+ case FLOW_START:
+ self->tx_flow = flow;
+ DEBUG(0, __FUNCTION__ "(), IrTTP wants us to start again\n");
+ wake_up_interruptible(sk->sleep);
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+ }
+}
+
+/*
+ * Function irda_get_value_confirm (obj_id, value, priv)
+ *
+ * Got answer from remote LM-IAS
+ *
+ */
+static void irda_get_value_confirm(__u16 obj_id, struct ias_value *value,
+ void *priv)
+{
+ struct irda_sock *self;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ ASSERT(priv != NULL, return;);
+ self = (struct irda_sock *) priv;
+
+ if (!self)
+ return;
+
+ /* Check if request succeeded */
+ if (!value) {
+ DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
+
+ /* Wake up any processes waiting for result */
+ wake_up_interruptible(&self->ias_wait);
+ return;
+ }
+
+ switch (value->type) {
+ case IAS_INTEGER:
+ DEBUG(4, __FUNCTION__ "() int=%d\n", value->t.integer);
+
+ if (value->t.integer != -1) {
+ self->dtsap_sel = value->t.integer;
+ } else
+ self->dtsap_sel = 0;
+ break;
+ default:
+ DEBUG(0, __FUNCTION__ "(), bad type!\n");
+ break;
+ }
+ /* Wake up any processes waiting for result */
+ wake_up_interruptible(&self->ias_wait);
+}
+
+/*
+ * Function irda_discovery_indication (log)
+ *
+ * Got a discovery log from IrLMP, wake ut any process waiting for answer
+ *
+ */
+static void irda_discovery_indication(hashbin_t *log)
+{
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ cachelog = log;
+
+ /* Wake up process if its waiting for device to be discovered */
+ wake_up_interruptible(&discovery_wait);
+}
+
+/*
+ * Function irda_open_tsap (self)
+ *
+ * Open local Transport Service Access Point (TSAP)
+ *
+ */
+static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
+{
+ struct notify_t notify;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ /* Initialize callbacks to be used by the IrDA stack */
+ irda_notify_init(&notify);
+ notify.connect_confirm = irda_connect_confirm;
+ notify.connect_indication = irda_connect_indication;
+ notify.disconnect_indication = irda_disconnect_indication;
+ notify.data_indication = irda_data_indication;
+ notify.flow_indication = irda_flow_indication;
+ notify.instance = self;
+ strncpy(notify.name, name, NOTIFY_MAX_NAME);
+
+ self->tsap = irttp_open_tsap(tsap_sel, DEFAULT_INITIAL_CREDIT,
+ &notify);
+ if (self->tsap == NULL) {
+ DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
+ return -1;
+ }
+ /* Remember which TSAP selector we actually got */
+ self->stsap_sel = self->tsap->stsap_sel;
X
-#ifdef IRDA_SOCKETS


+ return 0;
+}
+

+/*
+ * Function irda_find_lsap_sel (self, name)
+ *
+ * Try to lookup LSAP selector in remote LM-IAS
+ *
+ */
+static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+{
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return -1;);
+
+ /* Query remote LM-IAS */
+ iriap_getvaluebyclass_request(name, "IrDA:TinyTP:LsapSel",
+ self->saddr, self->daddr,
+ irda_get_value_confirm, self);
+ /* Wait for answer */
+ interruptible_sleep_on(&self->ias_wait);
+
+ if (self->dtsap_sel)
+ return 0;
+
+ return -ENETUNREACH; /* May not be true */
+}
X
X /*
X * Function irda_getname (sock, uaddr, uaddr_len, peer)
X *
- *
+ * Return the our own, or peers socket address (sockaddr_irda)
X *
X */
-static int irda_getname( struct socket *sock, struct sockaddr *uaddr,
- int *uaddr_len, int peer)
+static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer)
X {
- DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+ struct sockaddr_irda saddr;
+ struct sock *sk = sock->sk;
+
+ if (peer) {
+ if (sk->state != TCP_ESTABLISHED)
+ return -ENOTCONN;
+
+ saddr.sir_family = AF_IRDA;
+ saddr.sir_lsap_sel = sk->protinfo.irda->dtsap_sel;
+ saddr.sir_addr = sk->protinfo.irda->daddr;
+ } else {
+ saddr.sir_family = AF_IRDA;
+ saddr.sir_lsap_sel = sk->protinfo.irda->stsap_sel;
+ saddr.sir_addr = sk->protinfo.irda->saddr;
+ }
+
+ DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel);
+ DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr);
+
+ if (*uaddr_len > sizeof (struct sockaddr_irda))
+ *uaddr_len = sizeof (struct sockaddr_irda);
+ memcpy(uaddr, &saddr, *uaddr_len);
X
X return 0;
X }
@@ -68,22 +389,148 @@
X /*
X * Function irda_listen (sock, backlog)
X *
- *
+ * Just move to the listen state
X *
X */
X static int irda_listen( struct socket *sock, int backlog)
X {
X struct sock *sk = sock->sk;
X
- if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) {
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ if (sk->type == SOCK_STREAM && sk->state != TCP_LISTEN) {
X sk->max_ack_backlog = backlog;
X sk->state = TCP_LISTEN;


+
X return 0;
X }

-
+
X return -EOPNOTSUPP;
X }
X
+/*
+ * Function irda_bind (sock, uaddr, addr_len)
+ *
+ * Used by servers to register their well known TSAP
+ *
+ */
+static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_irda *addr = (struct sockaddr_irda *) uaddr;
+ struct irda_sock *self;
+ __u16 hints = 0;
+ int err;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = sk->protinfo.irda;
+ ASSERT(self != NULL, return -1;);
+
+ if ((addr_len < sizeof(struct sockaddr_irda)) ||
+ (addr_len > sizeof(struct sockaddr_irda)))
+ return -EINVAL;
+
+ err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
+ if (err < 0)
+ return -ENOMEM;
+
+ /* Register with LM-IAS */
+ self->ias_obj = irias_new_object(addr->sir_name, jiffies);
+ irias_add_integer_attrib(self->ias_obj, "IrDA:TinyTP:LsapSel",
+ self->stsap_sel);
+ irias_insert_object(self->ias_obj);
+
+ /* Fill in some default hint bits values */
+ if (strncmp(addr->sir_name, "OBEX", 4) == 0)
+ hints = irlmp_service_to_hint(S_OBEX);
+
+ if (hints)
+ self->skey = irlmp_register_service(hints);


+
+ return 0;
+}
+

+/*
+ * Function irda_accept (sock, newsock, flags)
+ *
+ * Wait for incomming connection
+ *
+ */
+static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+ struct irda_sock *self, *new;
+ struct sock *sk = sock->sk;
+ struct sock *newsk;
+ struct sk_buff *skb;
+
+ self = sk->protinfo.irda;
+ ASSERT(self != NULL, return -1;);
+
+ if (sock->state != SS_UNCONNECTED)
+ return -EINVAL;
+
+ if ((sk = sock->sk) == NULL)
+ return -EINVAL;
+
+ if (sk->type != SOCK_STREAM)
+ return -EOPNOTSUPP;
+
+ if (sk->state != TCP_LISTEN)
+ return -EINVAL;
+
+ /*
+ * The read queue this time is holding sockets ready to use
+ * hooked into the SABM we saved
+ */
+ do {
+ if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {
+ if (flags & O_NONBLOCK)
+ return -EWOULDBLOCK;
+
+ interruptible_sleep_on(sk->sleep);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+ } while (skb == NULL);
+
+ newsk = newsock->sk;
+ newsk->state = TCP_ESTABLISHED;
+
+ new = newsk->protinfo.irda;
+ ASSERT(new != NULL, return -1;);
+
+ /* Now attach up the new socket */
+ new->tsap = irttp_dup(self->tsap, new);
+ if (!new->tsap) {
+ DEBUG(0, __FUNCTION__ "(), dup failed!\n");


+ return -1;
+ }
+

+ new->stsap_sel = new->tsap->stsap_sel;
+ new->dtsap_sel = new->tsap->dtsap_sel;
+ new->saddr = irttp_get_saddr(new->tsap);
+ new->saddr = irttp_get_saddr(new->tsap);
+
+ new->max_sdu_size_tx = self->max_sdu_size_tx;
+ new->max_sdu_size_rx = self->max_sdu_size_rx;
+ memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info));
+
+ /* Clean up the original one to keep it in listen state */
+ self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
+ self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+
+ skb->sk = NULL;
+ skb->destructor = NULL;
+ kfree_skb(skb);
+ sk->ack_backlog--;
+
+ newsock->state = SS_CONNECTED;
+
+ irda_connect_response(new);
+


+ return 0;
+}
X
X /*

X * Function irda_connect (sock, uaddr, addr_len, flags)
@@ -91,17 +538,18 @@
X * Connect to a IrDA device
X *
X */
-static int irda_connect( struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags)
+static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len, int flags)
X {
-#if 0
- struct sock *sk = (struct sock *)sock->data;
- struct sockaddr_irda *addr = (struct sockaddr_irda *)uaddr;
- irda_address *user, *source = NULL;
- struct device *dev;
+ struct sock *sk = sock->sk;
+ struct sockaddr_irda *addr = (struct sockaddr_irda *) uaddr;
+ struct irda_sock *self;
+ int err;
+
+ self = sk->protinfo.irda;
+
+ DEBUG(1, __FUNCTION__ "()\n");
X

- DEBUG( 0, __FUNCTION__ "()\n");

-
X if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
X sock->state = SS_CONNECTED;
X return 0; /* Connect completed during a ERESTARTSYS event */
@@ -121,6 +569,36 @@
X if (addr_len != sizeof(struct sockaddr_irda))
X return -EINVAL;
X
+ /* Check if user supplied the required destination device address */
+ if (!addr->sir_addr)
+ return -EINVAL;
+
+ self->daddr = addr->sir_addr;
+ DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
+
+ /* Query remote LM-IAS */
+ err = irda_find_lsap_sel(self, addr->sir_name);
+ if (err) {
+ DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+ return err;
+ }
+
+ /* Check if we have opened a local TSAP */
+ if (!self->tsap)
+ irda_open_tsap(self, LSAP_ANY, addr->sir_name);
+
+ /* Move to connecting socket, start sending Connect Requests */
+ sock->state = SS_CONNECTING;
+ sk->state = TCP_SYN_SENT;
+
+ /* Connect to remote device */
+ err = irttp_connect_request(self->tsap, self->dtsap_sel,
+ self->saddr, self->daddr, NULL,
+ self->max_sdu_size_rx, NULL);
+ if (err) {
+ DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+ return err;
+ }
X
X /* Now the loop */
X if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
@@ -130,9 +608,9 @@
X
X /* A Connect Ack with Choke or timeout or failed routing will go to
X * closed. */
- while ( sk->state == TCP_SYN_SENT) {
- interruptible_sleep_on( sk->sleep);
- if (current->signal & ~current->blocked) {
+ while (sk->state == TCP_SYN_SENT) {
+ interruptible_sleep_on(sk->sleep);
+ if (signal_pending(current)) {
X sti();
X return -ERESTARTSYS;
X }
@@ -141,13 +619,13 @@
X if (sk->state != TCP_ESTABLISHED) {
X sti();
X sock->state = SS_UNCONNECTED;
- return sock_error( sk); /* Always set at this point */
+ return sock_error(sk); /* Always set at this point */
X }
X
X sock->state = SS_CONNECTED;
-
+
X sti();
-#endif


+
X return 0;
X }
X

@@ -160,51 +638,79 @@
X static int irda_create(struct socket *sock, int protocol)
X {
X struct sock *sk;
+ struct irda_sock *self;


X
- DEBUG( 0, __FUNCTION__ "()\n");

-
- /* Compatibility */
- if (sock->type == SOCK_PACKET) {
- static int warned;
- if (net_families[PF_PACKET]==NULL)
- {
-#if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
- char module_name[30];
- sprintf(module_name,"net-pf-%d", PF_PACKET);
- request_module(module_name);
- if (net_families[PF_PACKET] == NULL)
-#endif
- return -ESOCKTNOSUPPORT;
- }
- if (!warned++)
- printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
- return net_families[PF_PACKET]->create(sock, protocol);
- }
+ DEBUG(2, __FUNCTION__ "()\n");
X
-/* if (sock->type != SOCK_SEQPACKET || protocol != 0) */
-/* return -ESOCKTNOSUPPORT; */
+ /* Check for valid socket type */
+ switch (sock->type) {
+ case SOCK_STREAM: /* FALLTHROUGH */
+ case SOCK_SEQPACKET:
+ break;
+ default:
+ return -ESOCKTNOSUPPORT;
+ }
X
X /* Allocate socket */
X if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1)) == NULL)
X return -ENOMEM;
X
+ self = kmalloc(sizeof(struct irda_sock), GFP_ATOMIC);
+ if (self == NULL)
+ return -ENOMEM;
+ memset(self, 0, sizeof(struct irda_sock));
+
+ self->sk = sk;
+ sk->protinfo.irda = self;
+
X sock_init_data(sock, sk);
X
X sock->ops = &irda_proto_ops;
X sk->protocol = protocol;
X
+ /* Register as a client with IrLMP */
+ self->ckey = irlmp_register_client(0, NULL, NULL);
+ self->mask = 0xffff;
+ self->rx_flow = self->tx_flow = FLOW_START;
+ self->max_sdu_size_rx = SAR_DISABLE; /* Default value */
+ self->nslots = 6; /* Default for now */
+
+ /* Notify that we are using the irda module, so nobody removes it */
+ irda_mod_inc_use_count();


+
X return 0;
X }
X

X /*
- * Function irda_destroy_socket (tsap)
+ * Function irda_destroy_socket (self)
X *
X * Destroy socket
X *
X */
-void irda_destroy_socket(struct tsap_cb *tsap)
+void irda_destroy_socket(struct irda_sock *self)


X {
- DEBUG( 0, __FUNCTION__ "()\n");

+ DEBUG(2, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return;);
+
+ /* Unregister with IrLMP */
+ irlmp_unregister_client(self->ckey);
+ irlmp_unregister_service(self->skey);
+
+ /* Unregister with LM-IAS */
+ if (self->ias_obj)
+ irias_delete_object(self->ias_obj->name);
+
+ if (self->tsap) {
+ irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
+ irttp_close_tsap(self->tsap);
+ self->tsap = NULL;
+ }
+
+ kfree(self);
+
+ /* Notify that we are not using the irda module anymore */
+ irda_mod_dec_use_count();
X
X return;
X }
@@ -215,41 +721,108 @@
X *
X *
X */
-static int irda_release( struct socket *sock, struct socket *peer)
+static int irda_release(struct socket *sock, struct socket *peer)
X {
-#if 0
- struct sock *sk = (struct sock *)sock->data;
+ struct sock *sk = sock->sk;


X
- DEBUG( 0, __FUNCTION__ "()\n");

+ DEBUG(1, __FUNCTION__ "()\n");
X
-
- if (sk == NULL) return 0;
+ if (sk == NULL)
+ return 0;
X
- if (sk->type == SOCK_SEQPACKET) {
+ sk->state = TCP_CLOSE;
+ sk->shutdown |= SEND_SHUTDOWN;
+ sk->state_change(sk);
+ sk->dead = 1;
X
-
- } else {
- sk->state = TCP_CLOSE;
- sk->shutdown |= SEND_SHUTDOWN;
- sk->state_change(sk);
- sk->dead = 1;
- irda_destroy_socket( sk->protinfo.irda);
- }
+ irda_destroy_socket(sk->protinfo.irda);
+
+ sock->sk = NULL;
+ sk->socket = NULL; /* Not used, but we should do this. */
X
- sock->data = NULL;
- sk->socket = NULL; /* Not used, but we should do this. **/
-#endif


X return 0;
X }
X

+/*
+ * Function irda_sendmsg (sock, msg, len, scm)
+ *
+ * Send message down to TinyTP
+ *
+ */
+static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+ struct scm_cookie *scm)
+{
+ struct sock *sk = sock->sk;
+/* struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; */
+ struct irda_sock *self;
+ struct sk_buff *skb;
+ unsigned char *asmptr;
+ int err;
+
+ DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+
+ if (msg->msg_flags & ~MSG_DONTWAIT)
+ return -EINVAL;
+
+ if (sk->shutdown & SEND_SHUTDOWN) {
+ send_sig(SIGPIPE, current, 0);
+ return -EPIPE;
+ }
+
+ self = sk->protinfo.irda;
+ ASSERT(self != NULL, return -1;);
+
+ /* Check if IrTTP is wants us to slow down */
+ while (self->tx_flow == FLOW_STOP) {
+ DEBUG(2, __FUNCTION__ "(), IrTTP is busy, going to sleep!\n");
+ interruptible_sleep_on(sk->sleep);
+
+ /* Check if we are still connected */
+ if (sk->state != TCP_ESTABLISHED)
+ return -ENOTCONN;
+ }
+
+ skb = sock_alloc_send_skb(sk, len + IRDA_MAX_HEADER, 0,
+ msg->msg_flags & MSG_DONTWAIT, &err);
+ if (!skb)
+ return -ENOBUFS;
+
+ skb_reserve(skb, IRDA_MAX_HEADER);
+
+ DEBUG(4, __FUNCTION__ "(), appending user data\n");
+ asmptr = skb->h.raw = skb_put(skb, len);
+ memcpy_fromiovec(asmptr, msg->msg_iov, len);
+
+ /*
+ * Just send the message to TinyTP, and let it deal with possible
+ * errors. No need to duplicate all that here
+ */
+ err = irttp_data_request(self->tsap, skb);
+ if (err) {
+ DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+ return err;
+ }
+ return len;
+}
+
+/*
+ * Function irda_recvmsg (sock, msg, size, flags, scm)
+ *
+ * Try to receive message and copy it to user
+ *
+ */
X static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size,
X int flags, struct scm_cookie *scm)
X {
+ struct irda_sock *self;
X struct sock *sk = sock->sk;
X struct sk_buff *skb;
X int copied, err;
X
- DEBUG(0, __FUNCTION__ "()\n");


+ DEBUG(4, __FUNCTION__ "()\n");

+
+ self = sk->protinfo.irda;
+ ASSERT(self != NULL, return -1;);
X
X skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
X flags & MSG_DONTWAIT, &err);
@@ -267,6 +840,20 @@
X
X skb_free_datagram(sk, skb);
X
+ /*
+ * Check if we have previously stopped IrTTP and we know
+ * have more free space in our rx_queue. If so tell IrTTP
+ * to start delivering frames again before our rx_queue gets
+ * empty
+ */
+ if (self->rx_flow == FLOW_STOP) {
+ if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
+ DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+ self->rx_flow = FLOW_START;
+ irttp_flow_request(self->tsap, FLOW_START);
+ }
+ }
+
X return copied;
X }
X
@@ -279,10 +866,11 @@
X }
X
X
-unsigned int irda_poll( struct file *file, struct socket *sock,
- struct poll_table_struct *wait)
+unsigned int irda_poll(struct file *file, struct socket *sock,
+ struct poll_table_struct *wait)
X {
X DEBUG(0, __FUNCTION__ "()\n");


+
X return 0;
X }
X

@@ -296,7 +884,7 @@
X {
X struct sock *sk = sock->sk;


X
- DEBUG( 0, __FUNCTION__ "()\n");

+ DEBUG(0, __FUNCTION__ "(), cmd=%#x\n", cmd);
X
X switch (cmd) {
X case TIOCOUTQ: {
@@ -343,13 +931,163 @@
X return -EINVAL;
X
X default:
- return dev_ioctl(cmd, (void *)arg);
+ return dev_ioctl(cmd, (void *) arg);
X }
X
X /*NOTREACHED*/


X return 0;
X }
X

+/*
+ * Function irda_setsockopt (sock, level, optname, optval, optlen)
+ *
+ * Set some options for the socket
+ *
+ */
+static int irda_setsockopt(struct socket *sock, int level, int optname,
+ char *optval, int optlen)
+{
+ struct sock *sk = sock->sk;
+ struct irda_sock *self;
+ int opt;
+
+ DEBUG(0, __FUNCTION__ "()\n");
+
+ self = sk->protinfo.irda;
+ ASSERT(self != NULL, return -1;);
+
+ if (level != SOL_IRLMP)
+ return -ENOPROTOOPT;
+
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(opt, (int *)optval))
+ return -EFAULT;
+
+ switch (optname) {
+ case IRLMP_IAS_SET:
+ DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
+ return 0;
+ case IRTTP_MAX_SDU_SIZE:
+ DEBUG(0, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
+ self->max_sdu_size_rx = opt;
+ break;
+ default:
+ return -ENOPROTOOPT;


+ }
+ return 0;
+}
+

+/*
+ * Function irda_getsockopt (sock, level, optname, optval, optlen)
+ *
+ *
+ *
+ */
+static int irda_getsockopt(struct socket *sock, int level, int optname,
+ char *optval, int *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct irda_sock *self;
+ struct irda_device_list *list;
+ __u8 optbuf[sizeof(struct irda_device_list) +
+ sizeof(struct irda_device_info)*10];
+ discovery_t *discovery;
+ int val = 0;
+ int len = 0;


+ int i = 0;
+

+ DEBUG(1, __FUNCTION__ "()\n");
+
+ self = sk->protinfo.irda;
+
+ if (level != SOL_IRLMP)
+ return -ENOPROTOOPT;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ switch (optname) {
+ case IRLMP_ENUMDEVICES:
+ DEBUG(1, __FUNCTION__ "(), IRLMP_ENUMDEVICES\n");
+
+ /* Tell IrLMP we want to be notified */
+ irlmp_update_client(self->ckey, self->mask, NULL,
+ irda_discovery_indication);
+
+ /* Do some discovery */
+ irlmp_discovery_request(self->nslots);
+
+ /* Devices my be discovered already */
+ if (!cachelog) {
+ DEBUG(2, __FUNCTION__ "(), no log!\n");
+
+ /* Sleep until device(s) discovered */
+ interruptible_sleep_on(&discovery_wait);
+ if (!cachelog)


+ return -1;
+ }
+

+ list = (struct irda_device_list *) optbuf;
+ /*
+ * Now, check all discovered devices (if any), and notify
+ * client only about the services that the client is
+ * interested in
+ */
+ discovery = (discovery_t *) hashbin_get_first(cachelog);
+ while (discovery != NULL) {
+ /* Mask out the ones we don't want */
+ if (discovery->hints.word & self->mask) {
+ /* Copy discovery information */
+ list->dev[i].saddr = discovery->saddr;
+ list->dev[i].daddr = discovery->daddr;
+ list->dev[i].charset = discovery->charset;
+ list->dev[i].hints[0] = discovery->hints.byte[0];
+ list->dev[i].hints[1] = discovery->hints.byte[1];


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 27'
echo 'File patch-2.2.6 is continued in part 28'
echo 28 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part28

#!/bin/sh
# this is part 28 of a 34 - part archive


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

if test "$Scheck" != 28; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

+ strncpy(list->dev[i].info, discovery->info, 22);
+ if (++i >= 10)
+ break;
+ }
+ discovery = (discovery_t *) hashbin_get_next(cachelog);
+ }
+ cachelog = NULL;
+
+ list->len = i;
+ len = sizeof(struct irda_device_list) +
+ sizeof(struct irda_device_info) * i;
+
+ DEBUG(1, __FUNCTION__ "(), len=%d, i=%d\n", len, i);
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+
+ if (copy_to_user(optval, &optbuf, len))
+ return -EFAULT;
+ break;
+ case IRTTP_MAX_SDU_SIZE:
+ if (self->max_sdu_size_tx != SAR_DISABLE)
+ val = self->max_sdu_size_tx;
+ else
+ /* SAR is disabled, so use the IrLAP data size
+ * instead */
+ val = self->qos_tx.data_size.value - IRDA_MAX_HEADER;
+
+ DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
+ len = sizeof(int);
+ if (put_user(len, optlen))
+ return -EFAULT;
+
+ if (copy_to_user(optval, &val, len))
+ return -EFAULT;


+ break;
+ default:
+ return -ENOPROTOOPT;
+ }
+

+ return 0;
+}
+

X static struct net_proto_family irda_family_ops =
X {
X PF_IRDA,
@@ -361,24 +1099,28 @@
X
X sock_no_dup,
X irda_release,
- sock_no_bind,
+ irda_bind,
X irda_connect,
X sock_no_socketpair,
- sock_no_accept,
+ irda_accept,
X irda_getname,
X irda_poll,
X irda_ioctl,
X irda_listen,
X irda_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
+ irda_setsockopt,
+ irda_getsockopt,
X sock_no_fcntl,
- sock_no_sendmsg,
+ irda_sendmsg,
X irda_recvmsg
X };
X
-#endif /* IRDA_SOCKETS */
-
+/*
+ * Function irda_device_event (this, event, ptr)


+ *
+ *
+ *
+ */

X static int irda_device_event(struct notifier_block *this, unsigned long event,
X void *ptr)
X {
@@ -412,7 +1154,7 @@
X {
X 0, /* MUTTER ntohs(ETH_P_IRDA),*/
X NULL,
- irlap_input, /* irda_driver_rcv, */
+ irlap_driver_rcv,
X NULL,
X NULL,
X };
@@ -449,6 +1191,7 @@
X * Remove IrDA protocol layer
X *
X */
+#ifdef MODULE
X void irda_proto_cleanup(void)
X {
X DEBUG( 4, __FUNCTION__ "\n");
@@ -463,4 +1206,4 @@
X
X return;
X }
-
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.5/linux/net/irda/discovery.c linux/net/irda/discovery.c
--- v2.2.5/linux/net/irda/discovery.c Wed Dec 31 16:00:00 1969
+++ linux/net/irda/discovery.c Thu Apr 15 05:42:42 1999
@@ -0,0 +1,245 @@
+/*********************************************************************
+ *
+ * Filename: discovery.c
+ * Version: 0.1
+ * Description: Routines for handling discoveries at the IrLMP layer
+ * Status: Experimental.
+ * Author: Dag Brattli <da...@cs.uit.no>
+ * Created at: Tue Apr 6 15:33:50 1999
+ * Modified at: Tue Apr 6 20:26:46 1999
+ * Modified by: Dag Brattli <da...@cs.uit.no>
+ *

+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.

+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#include <linux/socket.h>
+#include <linux/irda.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+
+#include <net/irda/discovery.h>
+
+/*
+ * Function irlmp_add_discovery (cachelog, discovery)


+ *
+ *
+ *
+ */

+void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery)
+{
+ discovery_t *old;
+


+ DEBUG(2, __FUNCTION__ "()\n");
+

+ /* Check if we have discovered this device before */
+ old = hashbin_remove(cachelog, discovery->daddr, NULL);
+ if (old)
+ kfree(old);
+
+ /* Insert the new and updated version */
+ hashbin_insert(cachelog, (QUEUE *) discovery, discovery->daddr, NULL);
+}
+
+/*
+ * Function irlmp_add_discovery_log (cachelog, log)


+ *
+ *
+ *
+ */

+void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
+{
+ discovery_t *discovery;
+


+ DEBUG(2, __FUNCTION__ "()\n");
+

+ /*
+ * If log is missing this means that IrLAP was unable to perform the
+ * discovery, so restart discovery again with just the half timeout
+ * of the normal one.
+ */
+ if (log == NULL) {
+ /* irlmp_start_discovery_timer(irlmp, 150); */
+ return;
+ }
+
+ discovery = (discovery_t *) hashbin_remove_first(log);


+ while (discovery != NULL) {

+ irlmp_add_discovery(cachelog, discovery);
+
+ discovery = (discovery_t *) hashbin_remove_first(log);
+ }
+
+ /* Delete the now empty log */
+ hashbin_delete(log, (FREE_FUNC) kfree);
+}
+
+/*
+ * Function irlmp_expire_discoveries (log, saddr, force)
+ *
+ * Go through all discoveries and expire all that has stayed to long
+ *
+ */
+void irlmp_expire_discoveries(hashbin_t *log, int saddr, int force)
+{
+ discovery_t *discovery, *curr;
+
+ DEBUG(3, __FUNCTION__ "()\n");
+
+ discovery = (discovery_t *) hashbin_get_first(log);


+ while (discovery != NULL) {

+ curr = discovery;
+
+ /* Be sure to be one item ahead */
+ discovery = (discovery_t *) hashbin_get_next(log);
+
+ /* Test if it's time to expire this discovery */
+ if ((curr->saddr == saddr) && (force ||
+ ((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT)))
+ {
+ curr = hashbin_remove(log, curr->daddr, NULL);
+ if (curr)
+ kfree(curr);
+ }
+ }
+}
+
+/*
+ * Function irlmp_dump_discoveries (log)
+ *
+ * Print out all discoveries in log
+ *
+ */
+void irlmp_dump_discoveries(hashbin_t *log)
+{
+ discovery_t *discovery;
+
+ ASSERT(log != NULL, return;);
+
+ discovery = (discovery_t *) hashbin_get_first(log);


+ while (discovery != NULL) {

+ DEBUG(0, "Discovery:\n");
+ DEBUG(0, " daddr=%08x\n", discovery->daddr);
+ DEBUG(0, " saddr=%08x\n", discovery->saddr);
+ DEBUG(0, " name=%s\n", discovery->info);
+
+ discovery = (discovery_t *) hashbin_get_next(log);
+ }
+}
+
+/*
+ * Function irlmp_find_device (name, saddr)
+ *
+ * Look through the discovery log at each of the links and try to find
+ * the device with the given name. Return daddr and saddr. If saddr is
+ * specified, that look at that particular link only (not impl).
+ */
+__u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
+{
+ discovery_t *d;
+ unsigned long flags;
+
+ spin_lock_irqsave(&irlmp->lock, flags);
+
+ /* Look at all discoveries for that link */
+ d = (discovery_t *) hashbin_get_first(cachelog);
+ while (d != NULL) {
+ DEBUG(1, "Discovery:\n");
+ DEBUG(1, " daddr=%08x\n", d->daddr);
+ DEBUG(1, " name=%s\n", d->info);
+
+ if (strcmp(name, d->info) == 0) {
+ *saddr = d->saddr;
+
+ spin_unlock_irqrestore(&irlmp->lock, flags);
+ return d->daddr;
+ }
+ d = (discovery_t *) hashbin_get_next(cachelog);
+ }
+
+ spin_unlock_irqrestore(&irlmp->lock, flags);


+
+ return 0;
+}
+
+/*

+ * Function proc_discovery_read (buf, start, offset, len, unused)
+ *
+ * Print discovery information in /proc file system
+ *
+ */
+int discovery_proc_read(char *buf, char **start, off_t offset, int len,
+ int unused)
+{
+ discovery_t *discovery;
+ unsigned long flags;
+ hashbin_t *cachelog = irlmp_get_cachelog();
+
+ if (!irlmp)
+ return len;
+
+ len = sprintf(buf, "IrLMP: Discovery log:\n\n");
+
+ save_flags(flags);
+ cli();
+

+ discovery = (discovery_t *) hashbin_get_first(cachelog);
+ while ( discovery != NULL) {

+ len += sprintf( buf+len, " name: %s,",
+ discovery->info);
+
+ len += sprintf( buf+len, " hint: ");
+ if ( discovery->hints.byte[0] & HINT_PNP)
+ len += sprintf( buf+len, "PnP Compatible ");
+ if ( discovery->hints.byte[0] & HINT_PDA)
+ len += sprintf( buf+len, "PDA/Palmtop ");
+ if ( discovery->hints.byte[0] & HINT_COMPUTER)
+ len += sprintf( buf+len, "Computer ");
+ if ( discovery->hints.byte[0] & HINT_PRINTER)
+ len += sprintf( buf+len, "Printer ");
+ if ( discovery->hints.byte[0] & HINT_MODEM)
+ len += sprintf( buf+len, "Modem ");
+ if ( discovery->hints.byte[0] & HINT_FAX)
+ len += sprintf( buf+len, "Fax ");
+ if ( discovery->hints.byte[0] & HINT_LAN)
+ len += sprintf( buf+len, "LAN Access ");
+
+ if ( discovery->hints.byte[1] & HINT_TELEPHONY)
+ len += sprintf( buf+len, "Telephony ");
+ if ( discovery->hints.byte[1] & HINT_FILE_SERVER)
+ len += sprintf( buf+len, "File Server ");
+ if ( discovery->hints.byte[1] & HINT_COMM)
+ len += sprintf( buf+len, "IrCOMM ");
+ if ( discovery->hints.byte[1] & HINT_OBEX)
+ len += sprintf( buf+len, "IrOBEX ");
+
+ len += sprintf(buf+len, ", saddr: 0x%08x",
+ discovery->saddr);
+
+ len += sprintf(buf+len, ", daddr: 0x%08x\n",
+ discovery->daddr);
+
+ len += sprintf( buf+len, "\n");
+
+ discovery = (discovery_t *) hashbin_get_next(cachelog);
+ }
+ restore_flags(flags);


+
+ return len;
+}

diff -u --recursive --new-file v2.2.5/linux/net/irda/ircomm/Makefile linux/net/irda/ircomm/Makefile
--- v2.2.5/linux/net/irda/ircomm/Makefile Tue Dec 22 14:16:59 1998
+++ linux/net/irda/ircomm/Makefile Thu Apr 15 05:42:42 1999
@@ -8,9 +8,9 @@
X # Note 2! The CFLAGS definition is now in the main makefile...
X
X O_TARGET := ircomm_n_vtd.o
-O_OBJS := ircomm_common.o attach.o irvtd.o irvtd_driver.o
+O_OBJS := ircomm_common.o irvtd_driver.o
X M_OBJS := ircomm.o ircomm_tty.o
-MI_OBJS := ircomm_common.o attach.o irvtd.o irvtd_driver.o
+MI_OBJS := ircomm_common.o irvtd_driver.o
X
X OX_OBJS +=
X
@@ -18,10 +18,10 @@
X
X ifeq ($(CONFIG_IRCOMM),m)
X ircomm.o: $(MI_OBJS)
- $(LD) $(LD_RFLAG) -r -o $@ ircomm_common.o attach.o
+ $(LD) $(LD_RFLAG) -r -o $@ ircomm_common.o
X
X ircomm_tty.o: $(MI_OBJS)
- $(LD) $(LD_RFLAG) -r -o $@ irvtd.o irvtd_driver.o
+ $(LD) $(LD_RFLAG) -r -o $@ irvtd_driver.o


X endif
X
X include $(TOPDIR)/Rules.make

diff -u --recursive --new-file v2.2.5/linux/net/irda/ircomm/attach.c linux/net/irda/ircomm/attach.c
--- v2.2.5/linux/net/irda/ircomm/attach.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/ircomm/attach.c Wed Dec 31 16:00:00 1969
@@ -1,360 +0,0 @@
-/*********************************************************************
- *
- * Filename: attach.c
- * Version:
- * Description: An implementation of IrCOMM service interface.
- * Status: Experimental.
- * Author: Takahide Higuchi <thig...@pluto.dti.ne.jp>
- *
- * Copyright (c) 1998, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
- * All Rights Reserved.
- *
- * 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.
- *
- * I, Takahide Higuchi, provide no warranty for any of this software.
- * This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-
-/*
- * ----------------------------------------------------------------------
- * IrIAS related things for IrCOMM
- * If you are to use ircomm layer, use ircomm_attach_cable to
- * setup it and register your program.
- * ----------------------------------------------------------------------
- */
-
-
-#include <linux/sched.h>
-#include <linux/tqueue.h>
-
-#include <net/irda/irlap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irias_object.h>
-
-#include <net/irda/ircomm_common.h>
-
-extern struct ircomm_cb **ircomm;
-struct ircomm_cb *discovering_instance;
-
-static void got_lsapsel(struct ircomm_cb * info);
-static void query_lsapsel(struct ircomm_cb * self);
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value,
- void *priv);
-
-#if 0
-static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $";
-#endif
-
-
-/*
- * handler for iriap_getvaluebyclass_request()
- *
- */
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value,void *priv)
-{
- struct ircomm_cb *self = (struct ircomm_cb *) priv;
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
- /* Check if request succeeded */
- if ( !value) {
- DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-
- return;
- }
-
- DEBUG(0, __FUNCTION__"type(%d)\n", value->type);
-
- switch(value->type){
-
- case IAS_OCT_SEQ:
- /*
- * FIXME:we should use data which came here
- * it is used for nothing at this time
- */
-
-#if 1
- DEBUG(0, "octet sequence is:\n");
- {
- int i;
- for ( i=0;i<value->len;i++)
- printk("%02x",
- (int)(*value->t.oct_seq + i) );
- printk("\n");
- }
-#endif
- query_lsapsel(self);
- break;
-
- case IAS_INTEGER:
- /* LsapSel seems to be sent to me */
-
- if ( value->t.integer == -1){
- DEBUG( 0, "ircomm_getvalue_confirm: invalid value!\n");
- return;
- }
- if(self->state == COMM_IDLE){
- self->dlsap = value->t.integer;
- got_lsapsel(self);
- }
- break;
-
- case IAS_STRING:
- DEBUG(0, __FUNCTION__":STRING is not implemented\n");
- DEBUG(0, __FUNCTION__":received string:%s\n", value->t.string);
- query_lsapsel(self); /* experiment */
- break;
-
- case IAS_MISSING:
- DEBUG( 0, __FUNCTION__":MISSING is not implemented\n");
- break;
-
- default:
- DEBUG( 0, __FUNCTION__":unknown type!\n");
- break;
- }
-}
-
-static void got_lsapsel(struct ircomm_cb * self)
-{
- struct notify_t notify;
-
- DEBUG(0, "ircomm:got_lsapsel: got peersap!(%d)\n", self->dlsap );
-
- /* remove tsap for server */
- irttp_close_tsap(self->tsap);
-
- /* create TSAP for initiater ... */
- irda_notify_init(&notify);
- notify.data_indication = ircomm_accept_data_indication;
- notify.connect_confirm = ircomm_accept_connect_confirm;
- notify.connect_indication = ircomm_accept_connect_indication;
- notify.flow_indication = ircomm_accept_flow_indication;
- notify.disconnect_indication = ircomm_accept_disconnect_indication;
- strncpy( notify.name, "IrCOMM cli", NOTIFY_MAX_NAME);
- notify.instance = self;
-
- self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
- &notify);
- ASSERT(self->tsap != NULL, return;);
-
- /*
- * invoke state machine
- * and notify that I'm ready to accept connect_request
- */
-
- ircomm_next_state(self, COMM_IDLE);
- if(self->d_handler)
- self->d_handler(self);
-}
-
-static void query_lsapsel(struct ircomm_cb * self)
-{
- DEBUG(0, "ircomm:query_lsapsel..\n");
-
- /*
- * since we've got Parameters field of IAS, we are to get peersap.
- */
-
- if (!(self->servicetype & THREE_WIRE_RAW)) {
- iriap_getvaluebyclass_request(
- "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
- self->saddr, self->daddr,
- ircomm_getvalue_confirm, self );
- } else {
- DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
- }
-}
-
-
-
-/*
- * ircomm_discovery_indication()
- * Remote device is discovered, try query the remote IAS to see which
- * device it is, and which services it has.
- */
-
-void ircomm_discovery_indication( DISCOVERY *discovery)
-{
- struct ircomm_cb *self;
-
- DEBUG( 0, "ircomm_discovery_indication\n");
-
- self = discovering_instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
-
- self->daddr = discovery->daddr;
- self->saddr = discovery->saddr;
-
- DEBUG( 0, "ircomm_discovery_indication:daddr=%08x\n", self->daddr);
-
- /* query "Parameters" attribute of LM-IAS */
-
- DEBUG(0, "ircomm:querying parameters..\n");
-#if 0
- iriap_getvaluebyclass_request(self->daddr, "IrDA:IrCOMM",
- "Parameters",
- ircomm_getvalue_confirm,
- self);
-#else
- query_lsapsel(self);
-#endif


- return;
-}
-
-

-struct ircomm_cb * ircomm_attach_cable( __u8 servicetype,
- struct notify_t notify,
- void *handler )
-{
- int i;
- struct ircomm_cb *self = NULL;
- struct notify_t server_notify;
- struct ias_object* obj;
-
- /* FIXME: it should not be hard coded */
- __u8 oct_seq[6] = { 0,1,4,1,1,1 };
-
- ASSERT(ircomm != NULL,return NULL;);
- DEBUG(0,"ircomm_attach_cable:\n");
-
-
- /* find free handle */
-
- for(i = 0; i < IRCOMM_MAX_CONNECTION; i++){
- ASSERT(ircomm[i] != NULL,return(NULL););
- if(!ircomm[i]->in_use){
- self = ircomm[i];
- break;
- }
- }
-
- if (!self){
- DEBUG(0,"ircomm_attach_cable:no free handle!\n");
- return (NULL);
- }
-
- self->in_use = 1;
- self->servicetype = servicetype;
-
- DEBUG(0,"attach_cable:servicetype:%d\n",servicetype);
- self->d_handler = handler;
- self->notify = notify;
-
- /* register server.. */
-
- /*
- * TODO: since server TSAP is currentry hard coded,
- * we can use *only one* IrCOMM connection.
- * We have to create one more TSAP and register IAS entry dynamically
- * each time when we are to allocate new server here.
- */
- irda_notify_init(&server_notify);
- server_notify.data_indication = ircomm_accept_data_indication;
- server_notify.connect_confirm = ircomm_accept_connect_confirm;
- server_notify.connect_indication = ircomm_accept_connect_indication;
- server_notify.flow_indication = ircomm_accept_flow_indication;
- server_notify.disconnect_indication = ircomm_accept_disconnect_indication;
- server_notify.instance = self;
- strncpy( server_notify.name, "IrCOMM srv", NOTIFY_MAX_NAME);
-
- self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
- &server_notify);
- if(!self->tsap){
- DEBUG(0,"ircomm:Sorry, failed to allocate server_tsap\n");


- return NULL;
- }
-

- /*
- * Register with LM-IAS
- */
- obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID);
- irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel",
- self->tsap->stsap_sel );
-
- /* FIXME: it should not be hard coded */
-
- irias_add_octseq_attrib( obj, "Parameters",
- &oct_seq[0], 6);
- irias_insert_object( obj);
-
-/* obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID); */
-/* irias_add_octseq_attrib( obj, "Parameters", len, &octseq); */
-/* irias_insert_object( obj); */
-
-
-
- /* and start discovering .. */
- discovering_instance = self;
-
- switch(servicetype){
- case NINE_WIRE:
- DEBUG(0,"ircomm_attach_cable:discovering..\n");
- irlmp_register_layer(S_COMM , CLIENT|SERVER, TRUE,
- ircomm_discovery_indication);
- break;
-
-/* case CENTRONICS: */
-/* case THREE_WIRE: */
-/* case THREE_WIRE_RAW: */
-
- default:
- DEBUG(0,"ircomm_attach_cable:requested servicetype is not "
- "implemented!\n");


- return NULL;
- }
-

- ircomm_next_state(self, COMM_IDLE);
- return (self);
-}
-
-int ircomm_detach_cable(struct ircomm_cb *self)
-{
- ASSERT( self != NULL, return -EIO;);
- ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
-
- DEBUG(0,"ircomm_detach_cable:\n");
-
- /* shutdown ircomm layer */
- if(self->state != COMM_IDLE ){
- DEBUG(0,"ircomm:detach_cable:not IDLE\n");
- if(self->state != COMM_WAITI)
- ircomm_disconnect_request(self, NULL);
- }
-
-
- switch(self->servicetype){
-/* case CENTRONICS: */
- case NINE_WIRE:
-/* case THREE_WIRE: */
- irlmp_unregister_layer( S_COMM, CLIENT|SERVER );
- break;
-
-/* case THREE_WIRE_RAW: */
-/* irlmp_unregister( S_COMM ) */
-/* irlmp_unregister( S_PRINTER) */
-/* break; */
-
- default:
- DEBUG(0,"ircomm_detach_cable:requested servicetype is not "
- "implemented!\n");
- return -ENODEV;
- }
-
- /* remove tsaps */
- if(self->tsap)
- irttp_close_tsap(self->tsap);
-
- self->tsap = NULL;
- self->in_use = 0;
-
- return 0;
-}
diff -u --recursive --new-file v2.2.5/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.2.5/linux/net/irda/ircomm/ircomm_common.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/ircomm/ircomm_common.c Thu Apr 15 05:42:42 1999
@@ -33,23 +33,19 @@
X #include <linux/proc_fs.h>
X #include <linux/init.h>
X
-#include <net/irda/irmod.h>
+#include <net/irda/irda.h>
X #include <net/irda/irlmp.h>
X #include <net/irda/iriap.h>
X #include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
X
X #include <net/irda/ircomm_common.h>
X
-#if 0
-static char *rcsid = "$Id: ircomm_common.c,v 1.13 1998/10/13 12:59:05 takahide Exp $";
-#endif
-static char *version = "IrCOMM_common, $Revision: 1.13 $ $Date: 1998/10/13 12:59:05 $ (Takahide Higuchi)";
-
-
+static char *revision_date = "Tue Mar 2 02:03:58 1999";
X
X
-static void ircomm_state_discovery( struct ircomm_cb *self,
- IRCOMM_EVENT event, struct sk_buff *skb );
+static void ircomm_state_discovery(struct ircomm_cb *self,
+ IRCOMM_EVENT event, struct sk_buff *skb );
X static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event,
X struct sk_buff *skb );
X static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event,
@@ -60,12 +56,35 @@
X struct sk_buff *skb );
X static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
X struct sk_buff *skb);
-void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
+static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
+
+static void ircomm_discovery_indication(discovery_t *discovery);
+static void ircomm_tx_controlchannel(struct ircomm_cb *self );
+static int ircomm_proc_read(char *buf, char **start, off_t offset,
+ int len, int unused);
+
+static void query_lsapsel(struct ircomm_cb * self);
+static void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value,

+ void *priv);
+
+

+static __u32 ckey;
+static __u32 skey;
+struct ircomm_cb *discovering_instance;
+
+/*
+ * debug parameter ircomm_cs:
+ * 0 = client/server, 1 = client only 2 = server only
+ * usage for example:
+ * insmod ircomm ircomm_cs=1
+ * LILO boot : Linux ircomm_cs=2 etc.
+ */
+
+static int ircomm_cs = 0;
+MODULE_PARM(ircomm_cs, "i");
+
X
-int ircomm_check_handle(int handle);
X
-static void ircomm_parse_control(struct ircomm_cb *self, struct sk_buff *skb,
- int type);
X static char *ircommstate[] = {
X "DISCOVERY",
X "IDLE",
@@ -109,9 +128,6 @@
X "IRCOMM_CONTROL_REQUEST",
X };
X
-int ircomm_proc_read(char *buf, char **start, off_t offset,
- int len, int unused);
-
X #ifdef CONFIG_PROC_FS
X extern struct proc_dir_entry proc_irda;
X struct proc_dir_entry proc_ircomm = {
@@ -132,13 +148,13 @@
X ircomm_state_conn,
X };
X
-
X __initfunc(int ircomm_init(void))
X {
X int i;
X
- printk( KERN_INFO "%s\n", version);
- DEBUG( 4, "ircomm_common:init_module\n");
+ printk( "Linux-IrDA: IrCOMM protocol ( revision:%s ) \n",
+ revision_date);
+ DEBUG( 4, __FUNCTION__"()\n");
X
X /* allocate master array */
X
@@ -146,7 +162,7 @@
X IRCOMM_MAX_CONNECTION,
X GFP_KERNEL);
X if ( ircomm == NULL) {
- printk( KERN_WARNING "IrCOMM: Can't allocate ircomm array!\n");
+ printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
X return -ENOMEM;
X }
X
@@ -158,7 +174,7 @@
X ircomm[i] = kmalloc( sizeof(struct ircomm_cb), GFP_KERNEL );
X
X if(!ircomm[i]){
- printk(KERN_ERR "ircomm:kmalloc failed!\n");
+ printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
X return -ENOMEM;
X }
X
@@ -194,14 +210,17 @@
X proc_register( &proc_irda, &proc_ircomm);
X #endif /* CONFIG_PROC_FS */
X
+
+ discovering_instance = NULL;


X return 0;
X }
X

+#ifdef MODULE
X void ircomm_cleanup(void)
X {
X int i;
X
- DEBUG( 4, "ircomm_common:cleanup_module\n");
+ DEBUG( 4, "ircomm:cleanup_module\n");
X /*
X * free some resources
X */
@@ -227,8 +246,9 @@
X
X #ifdef CONFIG_PROC_FS
X proc_unregister( &proc_irda, proc_ircomm.low_ino);
-#endif
+#endif /* CONFIG_PROC_FS */
X }
+#endif /* MODULE */
X
X /*
X * ----------------------------------------------------------------------
@@ -236,23 +256,26 @@
X * ----------------------------------------------------------------------
X */
X
-void ircomm_accept_data_indication(void *instance, void *sap,
- struct sk_buff *skb)
+static int ircomm_accept_data_indication(void *instance, void *sap,
+ struct sk_buff *skb)
X {
X
X struct ircomm_cb *self = (struct ircomm_cb *)instance;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRCOMM_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT( self != NULL, return -1;);
+ ASSERT( self->magic == IRCOMM_MAGIC, return -1;);
+ ASSERT( skb != NULL, return -1;);
X
- DEBUG(4,"ircomm_accept_data_indication:\n");
+ DEBUG(4,__FUNCTION__"():\n");
X ircomm_do_event( self, TTP_DATA_INDICATION, skb);
+ self->rx_packets++;
+

+ return 0;
X }
X

-void ircomm_accept_connect_confirm(void *instance, void *sap,
+static void ircomm_accept_connect_confirm(void *instance, void *sap,
X struct qos_info *qos,
- int maxsdusize, struct sk_buff *skb)
+ __u32 maxsdusize, struct sk_buff *skb)
X {
X
X struct ircomm_cb *self = (struct ircomm_cb *)instance;
@@ -262,7 +285,7 @@
X ASSERT( skb != NULL, return;);
X ASSERT( qos != NULL, return;);
X
- DEBUG(0,"ircomm_accept_connect_confirm:\n");
+ DEBUG(0,__FUNCTION__"(): got connected!\n");
X
X if(maxsdusize == SAR_DISABLE)
X self->max_txbuff_size = qos->data_size.value;
@@ -277,9 +300,9 @@
X ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb);
X }
X
-void ircomm_accept_connect_indication(void *instance, void *sap,
+static void ircomm_accept_connect_indication(void *instance, void *sap,
X struct qos_info *qos,
- int maxsdusize,
+ __u32 maxsdusize,
X struct sk_buff *skb )
X {
X struct ircomm_cb *self = (struct ircomm_cb *)instance;
@@ -289,7 +312,7 @@
X ASSERT( skb != NULL, return;);
X ASSERT( qos != NULL, return;);
X
- DEBUG(0,"ircomm_accept_connect_indication:\n");
+ DEBUG(0,__FUNCTION__"()\n");
X
X if(maxsdusize == SAR_DISABLE)
X self->max_txbuff_size = qos->data_size.value;
@@ -298,9 +321,14 @@
X
X self->qos = qos;
X ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
+
+ /* stop connecting */
+ wake_up_interruptible( &self->discovery_wait);
+ wake_up_interruptible( &self->ias_wait);
+
X }
X
-void ircomm_accept_disconnect_indication(void *instance, void *sap,
+static void ircomm_accept_disconnect_indication(void *instance, void *sap,
X LM_REASON reason,
X struct sk_buff *skb)
X {
@@ -308,15 +336,16 @@
X
X ASSERT( self != NULL, return;);
X ASSERT( self->magic == IRCOMM_MAGIC, return;);
- ASSERT( skb != NULL, return;);
X
- DEBUG(0,"ircomm_accept_disconnect_indication:\n");
+ DEBUG(0,__FUNCTION__"():\n");
X ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
+
X }
X
-void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd)
+static void ircomm_accept_flow_indication( void *instance, void *sap,
+ LOCAL_FLOW cmd)
X {
-
+ IRCOMM_CMD command;
X struct ircomm_cb *self = (struct ircomm_cb *)instance;
X
X ASSERT( self != NULL, return;);


@@ -324,34 +353,32 @@
X

X switch(cmd){
X case FLOW_START:
- DEBUG(0,"ircomm_accept_flow_indication:START\n");
-
- self->pi = TX_READY;
+ DEBUG(4,__FUNCTION__"():START\n");
+ command = TX_READY;
X self->ttp_stop = 0;
X if(self->notify.flow_indication)
X self->notify.flow_indication( self->notify.instance,
- self, cmd);
- ircomm_control_request(self);
+ self, command);
X break;
X
X case FLOW_STOP:
- DEBUG(0,"ircomm_accept_flow_indication:STOP\n");
- self->pi = TX_BUSY;
+ DEBUG(4,__FUNCTION__":STOP\n");
+ command = TX_BUSY;
X self->ttp_stop = 1;
X if(self->notify.flow_indication)
X self->notify.flow_indication( self->notify.instance,
- self, cmd);
+ self, command);
X break;
X
X default:
- DEBUG(0,"ircomm_accept_flow_indication:unknown status!\n");
+ DEBUG(0,__FUNCTION__"();unknown status!\n");
X }
X
X }
X
X /*
X * ----------------------------------------------------------------------
- * Implementation of actions,descrived in section 7.4 of the reference.
+ * Impl. of actions (descrived in section 7.4 of the reference)
X * ----------------------------------------------------------------------
X */
X
@@ -360,33 +387,25 @@
X {
X /* TODO: we have to send/build userdata field which contains
X InitialControlParameters */
- /* but userdata field is not implemeted in irttp.c.. */
X
X switch(self->servicetype){
X case THREE_WIRE_RAW:
- /* not implemented yet! Do nothing */
- DEBUG(0, "ircomm:issue_connect_request:"
- "not implemented servicetype!");
+ DEBUG(0, __FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
X break;
X
X case DEFAULT:
- irttp_connect_request(self->tsap, self->dlsap,
- self->saddr, self->daddr,
- NULL, self->maxsdusize, NULL);
- break;
-
X case THREE_WIRE:
X case NINE_WIRE:
X case CENTRONICS:
X
X irttp_connect_request(self->tsap, self->dlsap,
X self->saddr, self->daddr,
- NULL, self->maxsdusize, NULL);
+ NULL, self->maxsdusize, userdata);
X break;
X
X default:
- DEBUG(0,"ircomm:issue_connect_request:Illegal servicetype %d\n"
- ,self->servicetype);
+ printk(KERN_ERR __FUNCTION__"():Illegal servicetype %d\n"
+ ,self->servicetype);
X }
X }
X
@@ -401,7 +420,7 @@
X if(self->notify.disconnect_indication)
X self->notify.disconnect_indication( self->notify.instance,
X self,
- self->reason,skb);
+ self->reason, skb);
X
X }
X
@@ -429,6 +448,7 @@
X
X static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
X {


+ DEBUG(4 ,__FUNCTION__"()\n");

X
X /* give a connect_confirm to the client */
X if( self->notify.connect_confirm )
@@ -440,11 +460,10 @@
X struct sk_buff *skb)
X {
X
- DEBUG(0,"ircomm:issue_connect_response:\n");
+ DEBUG(0,__FUNCTION__"()\n");
X
X if( self->servicetype == THREE_WIRE_RAW){
- DEBUG(0,"ircomm:issue_connect_response():3WIRE-RAW is not "
- "implemented yet !\n");
+ DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
X /* irlmp_connect_rsp(); */
X } else {
X irttp_connect_response(self->tsap, self->maxsdusize, skb);
@@ -455,10 +474,11 @@
X struct sk_buff *userdata)
X {
X if(self->servicetype == THREE_WIRE_RAW){
- DEBUG(0,"ircomm:issue_disconnect_request():3wireraw is not implemented!");
+ DEBUG(0,__FUNCTION__"():3wireraw is not implemented\n");
X }
X else
- irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
+ irttp_disconnect_request(self->tsap, userdata,
+ self->disconnect_priority);
X }
X
X static void issue_data_request(struct ircomm_cb *self,
@@ -468,52 +488,74 @@
X
X if(self->servicetype == THREE_WIRE_RAW){
X /* irlmp_data_request(self->lmhandle,userdata); */
- DEBUG(0,"ircomm:issue_data_request():not implemented!");
+ DEBUG(0,__FUNCTION__"():not implemented!");
X return;
X }
X
- DEBUG(4,"ircomm:issue_data_request():sending frame\n");
+ DEBUG(4,__FUNCTION__"():sending frame\n");
X err = irttp_data_request(self->tsap , userdata );
- if(err)
- DEBUG(0,"ircomm:ttp_data_request failed\n");
- if(userdata && err)
- dev_kfree_skb( userdata);
-
+ if(err){
+ printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n");
+ if(userdata)
+ dev_kfree_skb( userdata);
+ }
+ self->tx_packets++;
X }
X
X static void issue_control_request(struct ircomm_cb *self,
X struct sk_buff *userdata )
X {
- if(self->servicetype == THREE_WIRE_RAW){
- DEBUG(0,"THREE_WIRE_RAW is not implemented\n");
+ int err;
+
+ DEBUG(4,__FUNCTION__"()\n");
+ if(self->servicetype == THREE_WIRE_RAW)
+ {
+ DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
X
- }else {
- irttp_data_request(self->tsap,userdata);
+ }
+ else
+ {
+ err = irttp_data_request(self->tsap,userdata);
+ if(err)
+ {
+ printk( __FUNCTION__"():ttp_data_request failed\n");
+ if(userdata)
+ dev_kfree_skb( userdata);
+ }
+ else
+ self->tx_controls++;
+
+ self->pending_control_tuples = 0;
X }
X }
X
X static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
X {
X
- DEBUG(4,"ircomm:process_data:skb_len is(%d),clen_is(%d)\n",
+ DEBUG(4,__FUNCTION__":skb->len=%d, ircomm header = 1, clen=%d\n",
X (int)skb->len ,(int)skb->data[0]);
X
- /*
- * we always have to parse control channel
- * (see page17 of IrCOMM standard)
+ /* we have to parse control channel when receiving. (see
+ * page17 of IrCOMM standard) but it is not parsed here since
+ * upper layer may have some receive buffer.
+ *
+ * hence upper layer have to parse it when it consumes a packet.
+ * -- TH
X */
X
- ircomm_parse_control(self, skb, CONTROL_CHANNEL);
+ /* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */
X
X if(self->notify.data_indication && skb->len)
X self->notify.data_indication(self->notify.instance, self,
X skb);
X }
X
-void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+int ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
X {
X /* Not implemented yet:THREE_WIRE_RAW service uses this function. */
X DEBUG(0,"ircomm_data_indication:not implemented yet!\n");
+


+ return 0;
X }
X
X

@@ -528,15 +570,15 @@
X struct sk_buff *skb)
X {
X
- DEBUG( 4, "ircomm_do_event: STATE = %s, EVENT = %s\n",
+ DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n",
X ircommstate[self->state], ircommevent[event]);
X (*state[ self->state ]) ( self, event, skb);
X }
X
-void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state)
+static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state)
X {
X self->state = state;
- DEBUG( 0, "ircomm_next_state: NEXT STATE = %d(%s), sv(%d)\n",
+ DEBUG( 0, __FUNCTION__": NEXT STATE=%d(%s), servicetype=(%d)\n",
X (int)state, ircommstate[self->state],self->servicetype);
X }
X
@@ -549,8 +591,7 @@
X static void ircomm_state_discovery( struct ircomm_cb *self,
X IRCOMM_EVENT event, struct sk_buff *skb )
X {
- DEBUG(0,"ircomm_state_discovery: "
- "why call me? \n");
+ printk(KERN_ERR __FUNCTION__"():why call me? something is wrong..\n");
X if(skb)
X dev_kfree_skb( skb);
X }
@@ -578,15 +619,13 @@
X
X case LMP_CONNECT_INDICATION:
X
- /* I think this is already done in irlpt_event.c */
-
- DEBUG(0,"ircomm_state_idle():LMP_CONNECT_IND is notimplemented!");
+ DEBUG(0,__FUNCTION__"():LMP_CONNECT_IND is notimplemented!");
X /* connect_indication_three_wire_raw(); */
X /* ircomm_next_state(self, COMM_WAITR); */
X break;
X
X default:
- DEBUG(0,"ircomm_state_idle():unknown event =%d(%s)\n",
+ DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
X event, ircommevent[event]);
X }
X }
@@ -616,7 +655,7 @@
X /* ircomm_next_state(self, COMM_IDLE); */
X /* break; */
X default:
- DEBUG(0,"ircomm_state_waiti:unknown event =%d(%s)\n",
+ DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
X event, ircommevent[event]);
X }
X }
@@ -636,8 +675,7 @@
X /* issue_connect_response */
X
X if(self->servicetype==THREE_WIRE_RAW){
- DEBUG(0,"ircomm:issue_connect_response:"
- "THREE_WIRE_RAW is not implemented!\n");
+ DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n");
X /* irlmp_connect_response(Vpeersap,
X * ACCEPT,null);
X */
@@ -677,19 +715,15 @@
X switch(event){
X case TTP_DATA_INDICATION:
X process_data(self, skb);
- /* stay CONN state*/
X break;
X case IRCOMM_DATA_REQUEST:
X issue_data_request(self, skb);
- /* stay CONN state*/
X break;
X /* case LMP_DATA_INDICATION: */
X /* ircomm_data_indicated(); */
-/* stay CONN state */
X /* break; */
X case IRCOMM_CONTROL_REQUEST:
X issue_control_request(self, skb);
- /* stay CONN state*/
X break;
X case TTP_DISCONNECT_INDICATION:
X ircomm_next_state(self, COMM_IDLE);
@@ -712,16 +746,189 @@
X
X /*
X * ----------------------------------------------------------------------
- * ircomm requests
+ * IrCOMM service interfaces and supporting functions
X *
X * ----------------------------------------------------------------------
X */
X
-
-void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize)
+int ircomm_query_ias_and_connect(struct ircomm_cb *self, __u8 servicetype)
X {
+ int retval=0;
+ __u16 hints;
+
+ ASSERT( self != NULL, return -EFAULT;);
+ ASSERT( self->magic == IRCOMM_MAGIC, return -EFAULT;);
+ DEBUG(4,__FUNCTION__"():servicetype = %d\n",servicetype);
X
X /*
+ * wait if another instance is discovering now
+ */
+ if(discovering_instance){
+ interruptible_sleep_on( &self->discovery_wait);
+ if(signal_pending(current)){
+ return -EINTR; /* cought a signal */
+ }
+ if(self->state == COMM_CONN)
+ return 0; /* got connected */
+ }
+ ASSERT(discovering_instance == NULL, return -EFAULT;);
+ discovering_instance = self;
+
+ /*
+ * start discovering
+ */
+ hints = irlmp_service_to_hint(S_COMM);
+
+ DEBUG(0,__FUNCTION__"():start discovering..\n");
+ switch (ircomm_cs) {
+ case 0:
+ skey = irlmp_register_service(hints);
+ ckey = irlmp_register_client(hints, ircomm_discovery_indication,
+ NULL);
+ break;
+
+ case 1: /* client only */
+ DEBUG( 0, __FUNCTION__"():client only mode\n");
+ ckey = irlmp_register_client(hints, ircomm_discovery_indication,
+ NULL);
+ break;
+
+ case 2: /* server only */
+ default:
+ DEBUG( 0, __FUNCTION__"():server only mode\n");
+ skey = irlmp_register_service(hints);
+ discovering_instance = NULL;


+ return 0;
+ }
+

+
+ /*
+ * waiting for discovery
+ */
+ interruptible_sleep_on( &self->discovery_wait);
+ if(signal_pending(current)){
+ retval = -EINTR; goto bailout; /* cought a signal */
+ }
+ if(self->state == COMM_CONN)
+ goto bailout; /* got connected */
+
+ /*
+ * query Parameters field of IAS and waiting for answer
+ */
+
+ self->servicetype = 0;
+ DEBUG(0, __FUNCTION__"():querying IAS: Parameters..\n");
+ iriap_getvaluebyclass_request( "IrDA:IrCOMM", "Parameters",


+ self->saddr, self->daddr,

+ ircomm_getvalue_confirm, self );
+
+ interruptible_sleep_on( &self->ias_wait);
+ if(signal_pending(current)){
+ retval = -EINTR; goto bailout; /* cought a signal */
+ }
+ if(self->state == COMM_CONN)
+ goto bailout; /* got connected */
+
+
+ /* really got Parameters field? */
+ if(self->ias_type != IAS_OCT_SEQ){
+ retval = -EFAULT;
+ goto bailout;
+ }
+
+ /*
+ * check if servicetype we want is available
+ */
+ self->peer_cap = self->servicetype;
+
+ DEBUG(0,__FUNCTION__"():peer capability is:\n");
+ DEBUG(0,"3wire raw: %s\n",((self->servicetype & THREE_WIRE_RAW) ? "yes":"no"));
+ DEBUG(0,"3wire : %s\n",((self->servicetype & THREE_WIRE) ? "yes":"no"));
+ DEBUG(0,"9wire : %s\n",((self->servicetype & NINE_WIRE) ? "yes":"no"));
+ DEBUG(0,"IEEE1284 : %s\n",((self->servicetype & CENTRONICS) ? "yes":"no"));
+
+ self->servicetype &= servicetype;
+ if(!(self->servicetype)){
+ retval = -ENODEV;
+ goto bailout;
+ }
+
+ /*
+ * then choose better one
+ */
+
+ if(self->servicetype & THREE_WIRE_RAW)
+ servicetype = THREE_WIRE_RAW;
+ if(self->servicetype & THREE_WIRE)
+ servicetype = THREE_WIRE;
+ if(self->servicetype & NINE_WIRE)
+ servicetype = NINE_WIRE;
+ if(self->servicetype & CENTRONICS)
+ servicetype = CENTRONICS;
+
+ self->servicetype = servicetype;
+#if 1
+ /*
+ * waiting for discovery again
+ */
+ interruptible_sleep_on( &self->discovery_wait);
+ if(signal_pending(current)){
+ retval = -EINTR; goto bailout; /* cought a signal */
+ }
+ if(self->state == COMM_CONN)
+ goto bailout; /* got connected */
+#endif
+ /*
+ * query lsapsel field and waiting for answer
+ */
+ query_lsapsel(self);
+ interruptible_sleep_on( &self->ias_wait);
+ if(signal_pending(current)){
+ retval = -EINTR; goto bailout; /* cought a signal */
+ }
+ if(self->state == COMM_CONN)
+ goto bailout; /* got connected */
+
+ /* really got Lsapsel field? */
+ if(self->ias_type != IAS_INTEGER){
+ retval = -EFAULT;
+ goto bailout;
+ }
+#if 1
+ /*
+ * waiting for discovery again...
+ */
+ interruptible_sleep_on( &self->discovery_wait);
+ if(signal_pending(current)){
+ retval = -EINTR; goto bailout; /* cought a signal */
+ }
+ if(self->state == COMM_CONN)
+ goto bailout; /* got connected */
+#endif
+
+ /* succeed! ready to connect */
+ discovering_instance = NULL;
+ ircomm_connect_request(self);
+ return 0;
+
+ bailout:
+ /* failed. not ready to connect */
+ discovering_instance = NULL;
+ irlmp_unregister_service(skey);
+ irlmp_unregister_client(ckey);
+ return retval;
+}
+
+/*
+ * ircomm_connect_request()
+ * Impl. of this function is differ from one of the reference.
+ * This functin does discovery as well as sending connect request
+ */
+
+
+void ircomm_connect_request(struct ircomm_cb *self)
+{
+ /*
X * TODO:build a packet which contains "initial control parameters"
X * and send it with connect_request
X */
@@ -729,14 +936,17 @@
X ASSERT( self != NULL, return;);
X ASSERT( self->magic == IRCOMM_MAGIC, return;);
X
- DEBUG(0,"ircomm_connect_request:\n");
X
- self->maxsdusize = maxsdusize;
+ DEBUG(0, __FUNCTION__"():sending connect_request...\n");
+
+ ircomm_control_request(self, SERVICETYPE); /*servictype*/
+
+ self->maxsdusize = SAR_DISABLE;
X ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL);
X }
X
X void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
- int maxsdusize)
+ __u32 maxsdusize)
X {
X
X ASSERT( self != NULL, return;);
@@ -753,11 +963,8 @@
X if(!userdata){
X /* FIXME: check for errors and initialize? DB */
X userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
- if(!userdata){
- DEBUG(0, __FUNCTION__"alloc_skb failed\n");
- return;
- }
- IS_SKB(userdata, return;);
+ ASSERT(userdata != NULL, return;);
+
X skb_reserve(userdata,COMM_HEADER_SIZE);
X }
X
@@ -771,33 +978,70 @@
X }
X
X void ircomm_disconnect_request(struct ircomm_cb *self,
- struct sk_buff *userdata)
+ struct sk_buff *userdata,
+ int priority)
X {
X
X ASSERT( self != NULL, return;);
X ASSERT( self->magic == IRCOMM_MAGIC, return;);
+ DEBUG(0,__FUNCTION__"()\n");
+
+ /* unregister layer */
+ switch (ircomm_cs) {
+ case 1: /* client only */
+ irlmp_unregister_client(ckey);
+ break;
+
+ case 2: /* server only */
+ irlmp_unregister_service(skey);
+ break;
+ case 0:
+ default:
+ irlmp_unregister_client(ckey);
+ irlmp_unregister_service(skey);
+ break;
+ }
X
- DEBUG(0,"ircomm_disconnect_request\n");
- ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL);
+ self->disconnect_priority = priority;
+ if(priority != P_HIGH)
+ self->disconnect_priority = P_NORMAL;
+
+ ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata);
X }
X
X
-void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
+int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
X {
+ __u8 * frame;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRCOMM_MAGIC, return;);
- ASSERT( userdata != NULL, return;);
+ DEBUG(4,__FUNCTION__"()\n");
+ ASSERT( self != NULL, return -EFAULT;);
+ ASSERT( self->magic == IRCOMM_MAGIC, return -EFAULT;);
+ ASSERT( userdata != NULL, return -EFAULT;);
X
+
X if(self->state != COMM_CONN){
- DEBUG(4,"ignore IRCOMM_DATA_REQUEST:not connected\n");
- if(userdata)
- dev_kfree_skb(userdata);
- return;
+ DEBUG(4,__FUNCTION__"():not connected, data is ignored\n");
+ return -EINVAL;
X }
X
- DEBUG(4,"ircomm_data_request\n");
+ if(self->ttp_stop)
+ return -EBUSY;
+
+ if(self->control_ch_pending){
+ /* send control_channel */
+ ircomm_tx_controlchannel(self);
+ }
+
+ if(self->ttp_stop)
+ return -EBUSY;
+
+ /* add "clen" field */
+ frame = skb_push(userdata,1);
+ frame[0]=0; /* without control channel */
+
X ircomm_do_event(self, IRCOMM_DATA_REQUEST, userdata);


+ return 0;
X }
X
X /*

@@ -807,20 +1051,25 @@
X * ----------------------------------------------------------------------
X */
X
-static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self )
+
+static void ircomm_tx_controlchannel(struct ircomm_cb *self )
X {
X
X __u8 clen;
X struct sk_buff *skb = self->ctrl_skb;
X
- DEBUG(4,"ircomm_tx_ctrlbuffer:\n");
+ DEBUG(4,__FUNCTION__"()\n");
+ /* 'self' should have been checked */
+ ASSERT(!self->ttp_stop, return ;);
+ ASSERT(self->state == COMM_CONN, return ;);
X
X /* add "clen" field */
X
X clen=skb->len;
- if(clen){
- skb_push(skb,1);
- skb->data[0]=clen;
+ ASSERT(clen != 0,return;);
+
+ skb_push(skb,1);
+ skb->data[0]=clen;
X
X #if 0
X printk("tx_ctrl:");
@@ -831,148 +1080,106 @@


X printk("\n");
X }

X #endif
-
- ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
-
- skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
- if (skb==NULL){
- DEBUG(0,"ircomm_tx_ctrlbuffer:alloc_skb failed!\n");
- return;
- }
- skb_reserve(skb,COMM_HEADER_SIZE);
- self->ctrl_skb = skb;
- }
-}
-
-
-void ircomm_control_request(struct ircomm_cb *self)
-{
X
- struct sk_buff *skb;
+ ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
+ self->control_ch_pending = 0;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRCOMM_MAGIC, return;);
+ skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+ ASSERT(skb != NULL, return ;);
X
- DEBUG(0, "ircomm_control_request:\n");
-
- if(self->ttp_stop || self->state != COMM_CONN){
- DEBUG(0,"ircomm_control_request:can't send it.. ignore it\n");
- return;
- }
-
- skb = self->ctrl_skb;
- IS_SKB(skb,return;);
-
- if(skb->len)
- ircomm_tx_ctrlbuffer(self);
+ skb_reserve(skb,COMM_HEADER_SIZE);
+ self->ctrl_skb = skb;
X }
X
X
X static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl ,
X __u8 *value)
X {
-
X __u8 *frame;
X struct sk_buff *skb;
- int i,c;
+ int i,c = 0;
+ unsigned long flags;
+
+ save_flags(flags);cli();
X
X skb = self->ctrl_skb;
X ASSERT(skb != NULL, return;);
- IS_SKB(skb,return;);
X
- /*if there is little room in the packet... */
-
- if(skb->len > COMM_DEFAULT_DATA_SIZE - COMM_HEADER_SIZE - (pl+2)){
- if(!self->ttp_stop && self->state == COMM_CONN){
-
- /* send a packet if we can */
- ircomm_tx_ctrlbuffer(self);
- skb = self->ctrl_skb;
- } else {
- DEBUG(0, "ircomm_append_ctrl:there's no room.. ignore it\n");
-
- /* TODO: we have to detect whether we have to resend some
- information after ttp_stop is cleared */
-
- /* self->resend_ctrl = 1; */
- return;
- }
+ if(skb_tailroom(skb) < (pl+2)){
+ DEBUG(0, __FUNCTION__"there's no room.. ignore it\n");
+ self->ignored_control_tuples++;
+ restore_flags(flags);
+ return;
X }
X
X frame = skb_put(skb,pl+2);
- c = 0;
X frame[c++] = instruction; /* PI */
X frame[c++] = pl; /* PL */
X for(i=0; i < pl ; i++)
X frame[c++] = *value++; /* PV */
-
+ restore_flags(flags);
+ self->pending_control_tuples++;
+ self->control_ch_pending = 1;
X }
X
X
X
X /*
- * ircomm_append_ctrl();
+ * ircomm_control_request();
X * this function is exported as a request to send some control-channel tuples
X * to peer device
X */
X
-void ircomm_append_ctrl(struct ircomm_cb *self, __u8 instruction)
+void ircomm_control_request(struct ircomm_cb *self, __u8 instruction)
X {
X
- __u8 pv[70];
+ __u8 pv[32]; /* 32 max, for PORT_NAME */
X __u8 *value = &pv[0];
X __u32 temp;
+ int notsupp=0;
X
X ASSERT( self != NULL, return;);
X ASSERT( self->magic == IRCOMM_MAGIC, return;);
X
- if(self->state != COMM_CONN)
- return;
-
X if(self->servicetype == THREE_WIRE_RAW){
- DEBUG(0,"THREE_WIRE_RAW shuold not use me!\n");
+ DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW shuold not use me!\n");
X return;
X }
X
- DEBUG(4,"ircomm_append_ctrl:\n");
+ DEBUG(4,__FUNCTION__"()\n");
X
X /* find parameter and its length */
X
- switch(instruction){
+ if(self->servicetype == THREE_WIRE) goto threewire;
+ if(self->servicetype == NINE_WIRE) goto ninewire;
X
- case POLL_FOR_LINE_SETTINGS:
- case STATUS_QUERY:
+
+ /* FIXME: centronics service is not fully implemented yet*/
+ switch(instruction){
X case IEEE1284_MODE_SUPPORT:
X case IEEE1284_DEVICEID:
X append_tuple(self,instruction,0,NULL);
X break;
-
- case SERVICETYPE:
- value[0] = self->servicetype;
- append_tuple(self,instruction,1,value);
+ case STATUS_QUERY:
+ append_tuple(self,instruction,0,NULL);
X break;
- case DATA_FORMAT:
- value[0] = self->data_format;
+ case SET_BUSY_TIMEOUT:
+ value[0] = self->busy_timeout;
X append_tuple(self,instruction,1,value);
X break;
- case FLOW_CONTROL:
- if(self->null_modem_mode){
+ case IEEE1284_ECP_EPP_DATA_TRANSFER:
+ value[0] = self->ecp_epp_mode;
+ value[1] = self->channel_or_addr;
+ append_tuple(self,instruction,2,value);
+ break;
+ default:
+ notsupp=1;
+ }
X
- /* inside out */
- value[0] = (self->flow_ctrl & 0x55) << 1;
- value[0] |= (self->flow_ctrl & 0xAA) >> 1;
- }else{
- value[0] = self->flow_ctrl;
- }
- append_tuple(self,instruction,1,value);
- break;
- case LINESTATUS:
- value[0] = self->line_status;
- append_tuple(self,instruction,1,value);
- break;
- case BREAK_SIGNAL:
- value[0] = self->break_signal;
- append_tuple(self,instruction,1,value);
+ ninewire:
+ switch(instruction){
+ case POLL_FOR_LINE_SETTINGS:
+ append_tuple(self,instruction,0,NULL);
X break;
X case DTELINE_STATE:
X if(self->null_modem_mode){
@@ -1003,8 +1210,42 @@
X value[0] = self->dce;
X append_tuple(self,instruction,1,value);
X break;
- case SET_BUSY_TIMEOUT:
- value[0] = self->busy_timeout;
+
+ default:
+ notsupp=1;
+ }
+
+ threewire:
+ switch(instruction){
+
+ case SERVICETYPE:
+ value[0] = self->servicetype;
+ append_tuple(self,instruction,1,value);
+ break;
+
+ case DATA_FORMAT:
+ value[0] = self->data_format;
+ append_tuple(self,instruction,1,value);
+ break;
+
+ case FLOW_CONTROL:
+ if(self->null_modem_mode){
+ /* inside out */
+ value[0] = (self->flow_ctrl & 0x55) << 1;
+ value[0] |= (self->flow_ctrl & 0xAA) >> 1;
+ }else{
+ value[0] = self->flow_ctrl;
+ }
+ append_tuple(self,instruction,1,value);
+ break;
+
+ case LINESTATUS:
+ value[0] = self->line_status;
+ append_tuple(self,instruction,1,value);
+ break;
+
+ case BREAK_SIGNAL:
+ value[0] = self->break_signal;
X append_tuple(self,instruction,1,value);
X break;
X
@@ -1020,12 +1261,6 @@
X append_tuple(self,instruction,2,value);
X break;
X
- case IEEE1284_ECP_EPP_DATA_TRANSFER:
- value[0] = self->ecp_epp_mode;
- value[1] = self->channel_or_addr;
- append_tuple(self,instruction,2,value);
- break;
-
X case DATA_RATE:
X temp = self->data_rate;
X value[3] = (__u8)((temp >> 24) & 0x000000ff);
@@ -1034,203 +1269,422 @@
X value[0] = (__u8)(temp & 0x000000ff);
X append_tuple(self,instruction,4,value);
X break;
-
X #if 0
X case PORT_NAME:
X case FIXED_PORT_NAME:
X temp = strlen(&self->port_name);
- if(temp < 70){
+ if(temp < 32){
X value = (__u8) (self->port_name);
X append_tuple(self,instruction,temp,value);
- }
- break;
+ }else
+ DEBUG(0,__FUNCTION__"() PORT_NAME:too long\n");
X #endif
-
-/* TODO: control tuples for centronics emulation is not implemented */
-/* case IEEE1284_MODE: */
+ break;
X
X default:
- DEBUG(0,"ircomm_append_ctrl:instruction(0x%02x)is not"
- "implemented\n",instruction);
+ if(notsupp)
+ DEBUG(0,__FUNCTION__"():instruction(0x%02x)is not"
+ "implemented\n",instruction);
X }
X
X
X }
X
-static void ircomm_parse_control(struct ircomm_cb *self,
- struct sk_buff *skb,
- int type)
+void ircomm_parse_tuples(struct ircomm_cb *self, struct sk_buff *skb, int type)
X {
X
X __u8 *data;
- __u8 pi,pl,pv[64];
+ __u8 pi,plen;
X int clen = 0;
- int i,indicate,count = 0;
+ int indicate=0;
X
-
- data = skb->data;
- if(type == IAS_PARAM)
- clen = ((data[count++] << 8) & data[count++]); /* MSB first */
- else /* CONTROL_CHANNEL */
- clen = data[count++];
+ ASSERT(skb != NULL, return;);


+ ASSERT(self != NULL, return ;);

+ ASSERT(self->magic == IRCOMM_MAGIC, return ;);
X
X
- if(clen == 0){
- skb_pull( skb, 1); /* remove clen field */
- return;
+#ifdef IRCOMM_DEBUG_TUPLE
+ DEBUG(0, __FUNCTION__"():tuple sequence is:\n");
+ {
+ int i;
+ for ( i=0;i< skb->len;i++)
+ printk("%02x", (__u8)(skb->data[i]));
+ printk("\n");
X }
+#endif
X
+ data = skb->data;
+ if(type == IAS_PARAM)
+ {
+ clen = (data[0] << 8) & 0xff00;
+ clen |= data[1] & 0x00ff;
+ ASSERT( clen <= (skb->len - 2) && clen <= 1024, goto corrupted;);
+ DEBUG(4, __FUNCTION__"():IAS_PARAM len = %d\n",clen );
+ skb_pull( skb, 2);
+ }
+ else
+ {
+ /* CONTROL_CHANNEL */
+ clen = data[0];
+ ASSERT( clen < skb->len, goto corrupted;);
+ DEBUG(4, __FUNCTION__"():CONTROL_CHANNEL:len = %d\n",clen );
+ skb_pull( skb, 1);
+ }
X
+ while( clen >= 2 ){
+ data = skb->data;
+ indicate = 0;
X
-
- while( count < clen ){
X /*
X * parse controlparameters and set value into structure
X */
- pi = data[count++];
- pl = data[count++];
-
- DEBUG(0, "parse_control:instruction(0x%02x)\n",pi) ;
+ pi = data[0];
+ plen = data[1];
X
+ ASSERT( clen >= 2+plen, goto corrupted; );
+ DEBUG(4, __FUNCTION__"():instruction=0x%02x,len=%d\n",
+ pi, plen) ;
X
- /* copy a tuple into pv[] */
X
-#ifdef IRCOMM_DEBUG_TUPLE
- printk("data:");
- for(i=0; i < pl; i++){
- pv[i] = data[count++];
- printk("%02x",pv[i]);
- }
- printk("\n");
-#else
- for(i=0; i < pl; i++)
- pv[i] = data[count++];
-#endif
+ switch(pi)
+ {
+ case POLL_FOR_LINE_SETTINGS:
+ ircomm_control_request(self, DTELINE_STATE);
+ break;
X
-
- /* parse pv */
- indicate = 0;
-
- switch(pi){
-
- /*
- * for 3-wire/9-wire/centronics
- */
-
X case SERVICETYPE:
- self->peer_servicetype = pv[0];
+ self->servicetype = data[2];
X break;
+
X case PORT_TYPE:
- self->peer_port_type = pv[0];
- break;
-#if 0
- case PORT_NAME:
- self->peer_port_name = *pv;
- break;
- case FIXED_PORT_NAME:
- self->peer_port_name = *pv;
- /*
- * We should not connect if user of IrCOMM can't
- * recognize the port name
- */
- self->port_name_critical = TRUE;
- break;
-#endif
- case DATA_RATE:
- self->peer_data_rate = (pv[3]<<24) & (pv[2]<<16)
- & (pv[1]<<8) & pv[0];
- indicate = 1;
+ self->peer_port_type = data[2];
X break;
+
X case DATA_FORMAT:
- self->peer_data_format = pv[0];
+ self->peer_data_format = data[2];
X break;
+
X case FLOW_CONTROL:
- self->peer_flow_ctrl = pv[0];
- indicate = 1;
- break;
- case XON_XOFF_CHAR:
- self->peer_xon_char = pv[0];
- self->peer_xoff_char = pv[1];
- indicate = 1;
- break;
- case ENQ_ACK_CHAR:
- self->peer_enq_char = pv[0];
- self->peer_ack_char = pv[1];
+ self->peer_flow_ctrl = data[2];
X indicate = 1;
X break;
+
X case LINESTATUS:
- self->peer_line_status = pv[0];
+ self->peer_line_status = data[2];
X indicate = 1;
X break;
+
X case BREAK_SIGNAL:
- self->peer_break_signal = pv[0];
+ self->peer_break_signal = data[2];
X /* indicate = 1; */
X break;
-
- /*
- * for 9-wire
- */
+
+ case DCELINE_STATE:
+ self->peer_dce = data[2];
+ indicate = 1;
+ break;
X
X case DTELINE_STATE:
X if(self->null_modem_mode){
X /* input DTR as {DSR & CD & RI} */
X self->peer_dce = 0;
- if(pv[0] & DELTA_DTR)
- self->peer_dce |= DELTA_DSR|DELTA_RI|DELTA_DCD;
- if(pv[0] & MCR_DTR)
- self->peer_dce |= MSR_DSR|MSR_RI|MSR_DCD;
-
+ if(data[2] & DELTA_DTR)
+ self->peer_dce |= (DELTA_DSR|
+ DELTA_RI|
+ DELTA_DCD);
+ if(data[2] & MCR_DTR)
+ self->peer_dce |= (MSR_DSR|
+ MSR_RI|
+ MSR_DCD);
X /* rts as cts */
- if(pv[0] & DELTA_RTS)
+ if(data[2] & DELTA_RTS)
X self->peer_dce |= DELTA_CTS;
- if(pv[0] & MCR_RTS)
+ if(data[2] & MCR_RTS)
X self->peer_dce |= MSR_CTS;
X }else{
- self->peer_dte = pv[0];
+ self->peer_dte = data[2];
X }
X indicate = 1;
X break;
+
+ case XON_XOFF_CHAR:
+ self->peer_xon_char = data[2];
+ self->peer_xoff_char = data[3];
+ indicate = 1;
+ break;
X
- case DCELINE_STATE:
- self->peer_dce = pv[0];
+ case ENQ_ACK_CHAR:
+ self->peer_enq_char = data[2];
+ self->peer_ack_char = data[3];
X indicate = 1;
X break;
X
- case POLL_FOR_LINE_SETTINGS:
- ircomm_append_ctrl(self, DTELINE_STATE);
- ircomm_control_request(self);
+ case DATA_RATE:
+ self->peer_data_rate = ( data[5]<<24
+ & data[4]<<16
+ & data[3]<<8
+ & data[2]);
+ indicate = 1;
+ break;
+
+ case PORT_NAME:
+ ASSERT(plen <= 32 , goto corrupted;);
+ memcpy(self->port_name, data + 2, plen);
+ *(__u8 *)(self->port_name+plen) = 0;
X break;
X
- /*
- * for centronics .... not implemented yet
+ case FIXED_PORT_NAME:
+ ASSERT(plen <= 32 , goto corrupted;);
+ memcpy(self->port_name, data + 2, plen);
+ *(__u8 *)(self->port_name+plen) = 0;
+ /*
+ * We should not connect if user of IrCOMM can't
+ * recognize the port name
X */
-/* case STATUS_QUERY: */
-/* case SET_BUSY_TIMEOUT: */
-/* case IEEE1284_MODE_SUPPORT: */
-/* case IEEE1284_DEVICEID: */
-/* case IEEE1284_MODE: */
-/* case IEEE1284_ECP_EPP_DATA_TRANSFER: */
-
- default:
- DEBUG(0, "ircomm_parse_control:not implemented "
- "instruction(%d)\n", pi);
+ self->port_name_critical = TRUE;
X break;
+


+ default:
+ DEBUG(0, __FUNCTION__

+ "():not implemented (PI=%d)\n", pi);
X }
X
- if(indicate && self->notify.flow_indication
- && type == CONTROL_CHANNEL){
-
- DEBUG(0,"ircomm:parse_control:indicating..:\n");
+
+ if(indicate &&
+ self->notify.flow_indication && type == CONTROL_CHANNEL)
+ {
+ DEBUG(4,__FUNCTION__":indicating..:\n");
X self->pi = pi;
X if(self->notify.flow_indication)
- self->notify.flow_indication(self->notify.instance, self, 0);
- indicate = 0;
+ self->notify.flow_indication(self->notify.instance,
+ self,
+ CONTROL_CHANNEL);
+ }
+ skb_pull(skb, 2+plen);
+ clen -= (2+plen);


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 28'
echo 'File patch-2.2.6 is continued in part 29'
echo 29 > _shar_seq_.tmp

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part31

#!/bin/sh
# this is part 31 of a 34 - part archive


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

if test "$Scheck" != 31; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

X
X irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);

+
+ return 0;
X }
X

X static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
@@ -317,7 +314,7 @@
X */
X static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
X struct qos_info *qos,
- int max_sdu_size,
+ __u32 max_sdu_size,


X struct sk_buff *skb)
X {

X struct irlan_cb *self;
@@ -448,7 +445,10 @@
X static void irlan_check_response_param(struct irlan_cb *self, char *param,
X char *value, int val_len)
X {
+#ifdef CONFIG_IRLAN_GRATUITOUS_ARP
X struct in_device *in_dev;
+#endif
+ __u16 tmp_cpu; /* Temporary value in host order */
X __u8 *bytes;
X int i;
X
@@ -515,12 +515,16 @@
X return;
X }
X if (strcmp(param, "CON_ARB") == 0) {
- self->client.recv_arb_val = le16_to_cpup(value);
+ memcpy(&tmp_cpu, value, 2); /* Align value */
+ le16_to_cpus(&tmp_cpu); /* Convert to host order */
+ self->client.recv_arb_val = tmp_cpu;
X DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n",
X self->client.recv_arb_val);
X }
X if (strcmp(param, "MAX_FRAME") == 0) {
- self->client.max_frame = le16_to_cpup(value);
+ memcpy(&tmp_cpu, value, 2); /* Align value */
+ le16_to_cpus(&tmp_cpu); /* Convert to host order */
+ self->client.max_frame = tmp_cpu;
X DEBUG(4, __FUNCTION__ "(), max frame=%d\n",
X self->client.max_frame);
X }
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.2.5/linux/net/irda/irlan/irlan_common.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlan/irlan_common.c Thu Apr 15 05:42:42 1999
@@ -6,7 +6,7 @@
X * Status: Experimental.


X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Wed Feb 17 23:49:10 1999
+ * Modified at: Wed Apr 7 17:03:21 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
@@ -55,6 +55,7 @@
X * Master structure
X */
X hashbin_t *irlan = NULL;
+static __u32 ckey, skey;
X
X /* Module parameters */
X static int eth = 0; /* Use "eth" or "irlan" name for devices */
@@ -143,6 +144,12 @@
X irlan_watchdog_timer_expired);
X }
X
+/*
+ * Function irlan_eth_open (dev)
+ *
+ * Network device has been opened by user
+ *
+ */
X static int irlan_eth_open(struct device *dev)
X {
X struct irlan_cb *self;
@@ -162,6 +169,9 @@
X
X self->notify_irmanager = TRUE;
X
+ /* We are now open, so time to do some work */
+ irlan_client_wakeup(self, self->saddr, self->daddr);
+
X MOD_INC_USE_COUNT;
X
X return 0;


@@ -196,7 +206,7 @@
X

X irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
X
- /* Device closed by user */
+ /* Device closed by user! */
X if (self->notify_irmanager)
X self->notify_irmanager = FALSE;
X else
@@ -233,7 +243,7 @@
X
X dev->tx_queue_len = TTP_MAX_QUEUE;
X
-#ifdef 0
+#if 0
X /*
X * OK, since we are emulating an IrLAN sever we will have to give
X * ourself an ethernet address!
@@ -274,6 +284,7 @@
X __initfunc(int irlan_init(void))
X {
X struct irlan_cb *new;
+ __u16 hints;
X
X DEBUG(4, __FUNCTION__"()\n");
X
@@ -289,12 +300,14 @@
X
X DEBUG(4, __FUNCTION__ "()\n");
X
- /* Register with IrLMP as a service user */
- irlmp_register_layer(S_LAN, CLIENT, TRUE,
- irlan_client_discovery_indication);
+ hints = irlmp_service_to_hint(S_LAN);
+
+ /* Register with IrLMP as a client */
+ ckey = irlmp_register_client(hints, irlan_client_discovery_indication,
+ NULL);
X
X /* Register with IrLMP as a service */
- irlmp_register_layer(S_LAN, SERVER, FALSE, NULL);
+ skey = irlmp_register_service(hints);
X
X /* Start the first IrLAN instance */
X new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
@@ -309,9 +322,9 @@
X {
X DEBUG(4, __FUNCTION__ "()\n");
X
- irlmp_unregister_layer(S_LAN, SERVER);
+ irlmp_unregister_client(ckey);
X
- irlmp_unregister_layer(S_LAN, CLIENT);
+ irlmp_unregister_service(skey);
X
X #ifdef CONFIG_PROC_FS
X proc_unregister(&proc_irda, proc_irlan.low_ino);
@@ -344,8 +357,7 @@
X self->dev.name = self->ifname;
X
X if (register_netdev(&self->dev) != 0) {
- DEBUG(2, __FUNCTION__
- "(), register_netdev() failed!\n");
+ DEBUG(2, __FUNCTION__ "(), register_netdev() failed!\n");
X return -1;
X }
X self->netdev_registered = TRUE;
@@ -472,7 +484,7 @@
X }
X
X void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
- int max_sdu_size, struct sk_buff *skb)
+ __u32 max_sdu_size, struct sk_buff *skb)
X {
X struct irlan_cb *self;
X struct tsap_cb *tsap;
@@ -505,7 +517,7 @@
X }
X
X void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos,
- int max_sdu_size, struct sk_buff *skb)
+ __u32 max_sdu_size, struct sk_buff *skb)
X {
X struct irlan_cb *self;
X
@@ -1043,6 +1055,7 @@
X {
X __u8 *frame;
X __u8 param_len;
+ __u16 tmp_le; /* Temporary value in little endian format */
X int n=0;
X
X if (skb == NULL) {
@@ -1085,7 +1098,8 @@
X memcpy(frame+n, param, param_len); n += param_len;
X
X /* Insert value length (2 byte little endian format, LSB first) */
- *((__u16 *) (frame+n)) = cpu_to_le16(value_len); n += 2;
+ tmp_le = cpu_to_le16(value_len);
+ memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */
X
X /* Insert value */
X switch (type) {
@@ -1093,7 +1107,8 @@
X frame[n++] = value_byte;
X break;
X case IRLAN_SHORT:
- *((__u16 *) (frame+n)) = cpu_to_le16(value_short); n += 2;
+ tmp_le = cpu_to_le16(value_short);
+ memcpy(frame+n, &tmp_le, 2); n += 2;
X break;
X case IRLAN_ARRAY:
X memcpy(frame+n, value_array, value_len); n+=value_len;
@@ -1137,7 +1152,8 @@
X * Get length of parameter value (2 bytes in little endian
X * format)
X */
- val_len = le16_to_cpup(buf+n); n+=2;
+ memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
+ le16_to_cpus(&val_len); n+=2;
X
X if (val_len > 1016) {
X DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
@@ -1277,9 +1293,7 @@
X */
X int init_module(void)
X {
- irlan_init();
-
- return 0;
+ return irlan_init();
X }
X
X /*
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.2.5/linux/net/irda/irlan/irlan_eth.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlan/irlan_eth.c Thu Apr 15 05:42:42 1999
@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Thu Oct 15 08:37:58 1998
- * Modified at: Wed Feb 3 19:58:28 1999
+ * Modified at: Mon Mar 22 17:41:59 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X * Sources: skeleton.c by Donald Becker <bec...@CESDIS.gsfc.nasa.gov>
X * slip.c by Laurence Culhane, <l...@holmes.demon.co.uk>
@@ -31,6 +31,7 @@
X #include <net/arp.h>
X
X #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
X #include <net/irda/irlan_common.h>
X #include <net/irda/irlan_eth.h>
X
@@ -123,20 +124,20 @@
X * This function gets the data that is received on the data channel
X *
X */
-void irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
+int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
X {
X struct irlan_cb *self;
X
X self = (struct irlan_cb *) instance;
X

- ASSERT(self != NULL, return;);

- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ ASSERT(self != NULL, return 0;);
+ ASSERT(self->magic == IRLAN_MAGIC, return 0;);
X
X if (skb == NULL) {
X ++self->stats.rx_dropped;
- return;
+ return 0;
X }
- ASSERT(skb->len > 1, return;);
+ ASSERT(skb->len > 1, return 0;);
X
X /*
X * Adopt this frame! Important to set all these fields since they
@@ -151,7 +152,7 @@
X self->stats.rx_packets++;
X self->stats.rx_bytes += skb->len;
X
-/* net_bh(); */


+ return 0;
X }
X
X /*

diff -u --recursive --new-file v2.2.5/linux/net/irda/irlan/irlan_filter.c linux/net/irda/irlan/irlan_filter.c
--- v2.2.5/linux/net/irda/irlan/irlan_filter.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlan/irlan_filter.c Thu Apr 15 05:42:42 1999
@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Fri Jan 29 11:16:38 1999
- * Modified at: Sun Feb 7 23:48:07 1999
+ * Modified at: Thu Feb 25 15:10:54 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -138,8 +138,8 @@
X * Check parameters in request from peer device
X *
X */
-static void irlan_check_command_param(struct irlan_cb *self, char *param,
- char *value)
+void irlan_check_command_param(struct irlan_cb *self, char *param,
+ char *value)
X {
X __u8 *bytes;
X
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c
--- v2.2.5/linux/net/irda/irlan/irlan_provider.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlan/irlan_provider.c Thu Apr 15 05:42:42 1999
@@ -6,7 +6,7 @@
X * Status: Experimental.


X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Thu Feb 4 16:08:33 1999
+ * Modified at: Tue Apr 6 19:08:20 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X * Sources: skeleton.c by Donald Becker <bec...@CESDIS.gsfc.nasa.gov>
X * slip.c by Laurence Culhane, <l...@holmes.demon.co.uk>
@@ -56,8 +56,8 @@
X * This function gets the data that is received on the control channel
X *
X */
-void irlan_provider_data_indication(void *instance, void *sap,
- struct sk_buff *skb)
+int irlan_provider_data_indication(void *instance, void *sap,

+ struct sk_buff *skb)
X {

X struct irlan_cb *self;
X __u8 code;
@@ -66,10 +66,10 @@
X
X self = (struct irlan_cb *) instance;
X

- ASSERT(self != NULL, return;);

- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRLAN_MAGIC, return -1;);
X
- ASSERT(skb != NULL, return;);
+ ASSERT(skb != NULL, return -1;);
X
X code = skb->data[0];
X switch(code) {
@@ -102,6 +102,7 @@
X DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
X break;
X }


+ return 0;
X }
X
X /*

@@ -111,8 +112,8 @@
X *
X */
X void irlan_provider_connect_indication(void *instance, void *sap,
- struct qos_info *qos, int max_sdu_size,
- struct sk_buff *skb)
+ struct qos_info *qos,
+ __u32 max_sdu_size, struct sk_buff *skb)
X {
X struct irlan_cb *self, *entry, *new;
X struct tsap_cb *tsap;
@@ -248,7 +249,6 @@
X __u8 *frame;
X __u8 *ptr;
X int count;
- __u8 name_len;
X __u16 val_len;
X int i;
X char *name;
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.2.5/linux/net/irda/irlap.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlap.c Thu Apr 15 05:42:42 1999
@@ -3,10 +3,10 @@
X * Filename: irlap.c
X * Version: 0.9
X * Description: An IrDA LAP driver for Linux
- * Status: Experimental.
+ * Status: Stable.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Sat Feb 20 01:39:58 1999
+ * Modified at: Tue Apr 6 21:07:08 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,
@@ -30,6 +30,7 @@
X #include <linux/delay.h>


X #include <linux/proc_fs.h>
X #include <linux/init.h>

+#include <linux/random.h>
X
X #include <net/irda/irda.h>
X #include <net/irda/irda_device.h>
@@ -127,11 +128,17 @@
X skb_queue_head_init( &self->tx_list);
X skb_queue_head_init( &self->wx_list);
X
- /* My unique IrLAP device address! :-) */
- self->saddr = jiffies;
+ /* My unique IrLAP device address! */
+ get_random_bytes(&self->saddr, sizeof(self->saddr));
X
- /* Generate random connection address for this session */
- self->caddr = jiffies & 0xfe;
+ /*
+ * Generate random connection address for this session, which must
+ * be 7 bits wide and different from 0x00 and 0xfe
+ */
+ while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
+ get_random_bytes(&self->caddr, sizeof(self->caddr));
+ self->caddr &= 0xfe;
+ }
X
X init_timer( &self->slot_timer);
X init_timer( &self->query_timer);
@@ -147,7 +154,7 @@
X
X hashbin_insert( irlap, (QUEUE *) self, self->saddr, NULL);
X
- irlmp_register_irlap( self, self->saddr, &self->notify);
+ irlmp_register_link( self, self->saddr, &self->notify);
X
X return self;
X }
@@ -181,9 +188,9 @@
X }
X
X /*
- * Function irlap_close ()
+ * Function irlap_close (self)
X *
- *
+ * Remove IrLAP instance
X *
X */
X void irlap_close( struct irlap_cb *self)

@@ -197,7 +204,7 @@
X

X irlap_disconnect_indication( self, LAP_DISC_INDICATION);
X
- irlmp_unregister_irlap( self->saddr);
+ irlmp_unregister_link(self->saddr);
X self->notify.instance = NULL;
X
X /* Be sure that we manage to remove ourself from the hash */
@@ -210,7 +217,7 @@
X }
X
X /*
- * Function irlap_connect_indication ()
+ * Function irlap_connect_indication (self, skb)
X *
X * Another device is attempting to make a connection
X *
@@ -229,31 +236,32 @@
X }
X
X /*
- * Function irlap_connect_response (void)
+ * Function irlap_connect_response (self, skb)
X *
X * Service user has accepted incomming connection
X *
X */
-void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb)
X {
X DEBUG( 4, __FUNCTION__ "()\n");
X
- irlap_do_event( self, CONNECT_RESPONSE, skb, NULL);
+ irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
X }
X
X /*
- * Function irlap_connect_request (daddr, qos, sniff)
+ * Function irlap_connect_request (self, daddr, qos_user, sniff)
X *
X * Request connection with another device, sniffing is not implemented
X * yet.
+ *
X */
-void irlap_connect_request( struct irlap_cb *self, __u32 daddr,
- struct qos_info *qos_user, int sniff)
+void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+ struct qos_info *qos_user, int sniff)
X {
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);


X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X self->daddr = daddr;
X
@@ -261,32 +269,33 @@
X * If the service user specifies QoS values for this connection,
X * then use them
X */
- irlap_init_qos_capabilities( self, qos_user);
+ irlap_init_qos_capabilities(self, qos_user);
X
- if ( self->state == LAP_NDM)
- irlap_do_event( self, CONNECT_REQUEST, NULL, NULL);
+ if ((self->state == LAP_NDM) &&
+ !irda_device_is_media_busy(self->irdev))
+ irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
X else
X self->connect_pending = TRUE;
X }
X
X /*
- * Function irlap_connect_confirm (void)
+ * Function irlap_connect_confirm (self, skb)
X *
- * Connection request is accepted
+ * Connection request has been accepted
X *
X */
-void irlap_connect_confirm( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
X {
- DEBUG( 4, __FUNCTION__ "()\n");


+ DEBUG(4, __FUNCTION__ "()\n");

X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LAP_MAGIC, return;);
X
- irlmp_link_connect_confirm( self->notify.instance, &self->qos_tx, skb);
+ irlmp_link_connect_confirm(self->notify.instance, &self->qos_tx, skb);
X }
X
X /*
- * Function irlap_data_indication (skb)
+ * Function irlap_data_indication (self, skb)
X *
X * Received data frames from IR-port, so we just pass them up to
X * IrLMP for further processing
@@ -451,7 +460,6 @@
X #ifdef CONFIG_IRDA_COMPRESSION
X irda_free_compression( self);
X #endif
-
X /* Flush queues */
X irlap_flush_all_queues( self);
X
@@ -479,7 +487,7 @@
X * Start one single discovery operation.
X *
X */
-void irlap_discovery_request( struct irlap_cb *self, DISCOVERY *discovery)
+void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
X {
X struct irlap_info info;
X
@@ -568,7 +576,7 @@
X * Somebody is trying to discover us!
X *
X */
-void irlap_discovery_indication( struct irlap_cb *self, DISCOVERY *discovery)
+void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery)
X {
X DEBUG( 4, __FUNCTION__ "()\n");
X
@@ -578,7 +586,7 @@
X
X ASSERT( self->notify.instance != NULL, return;);
X
- irlmp_discovery_indication( self->notify.instance, discovery);
+ irlmp_link_discovery_indication(self->notify.instance, discovery);
X }
X
X /*
@@ -587,7 +595,7 @@


X *
X *
X */

-void irlap_status_indication( int quality_of_link)
+void irlap_status_indication(int quality_of_link)
X {
X switch( quality_of_link) {
X case STATUS_NO_ACTIVITY:
@@ -599,7 +607,7 @@
X default:
X break;
X }
- irlmp_status_indication( quality_of_link, NO_CHANGE);
+ irlmp_status_indication(quality_of_link, LOCK_NO_CHANGE);
X }
X
X /*
@@ -629,7 +637,7 @@
X */
X void irlap_reset_confirm(void)
X {
- DEBUG( 1, __FUNCTION__ "()\n");
+ DEBUG( 1, __FUNCTION__ "()\n");
X }
X
X /*
@@ -795,7 +803,7 @@
X * frame in order to delay for the specified amount of time. This is
X * done to avoid using timers, and the forbidden udelay!
X */
-void irlap_wait_min_turn_around( struct irlap_cb *self, struct qos_info *qos)
+void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos)
X {
X int usecs;
X int speed;
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.2.5/linux/net/irda/irlap_event.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlap_event.c Thu Apr 15 05:42:42 1999
@@ -6,7 +6,7 @@


X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Sat Aug 16 00:59:29 1997
- * Modified at: Thu Feb 11 00:38:58 1999
+ * Modified at: Fri Mar 26 14:24:09 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,
@@ -84,6 +84,7 @@
X "RECV_DISCOVERY_XID_RSP",
X "RECV_SNRM_CMD",
X "RECV_TEST_CMD",
+ "RECV_TEST_RSP",
X "RECV_UA_RSP",
X "RECV_DM_RSP",
X "RECV_I_CMD",
@@ -206,13 +207,13 @@
X {
X int ret;
X
- if ( !self || self->magic != LAP_MAGIC)
+ if (!self || self->magic != LAP_MAGIC)
X return;
X
- DEBUG( 4, __FUNCTION__ "(), event = %s, state = %s\n",
- irlap_event[ event], irlap_state[ self->state]);
+ DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n",
+ irlap_event[ event], irlap_state[ self->state]);
X
- ret = (*state[ self->state]) ( self, event, skb, info);
+ ret = (*state[ self->state]) (self, event, skb, info);
X
X /*
X * Check if there are any pending events that needs to be executed
@@ -243,7 +244,9 @@
X break;
X case LAP_NDM:
X /* Check if we should try to connect */
- if (self->connect_pending) {
+ if ((self->connect_pending) &&
+ !irda_device_is_media_busy(self->irdev))
+ {
X self->connect_pending = FALSE;
X
X ret = (*state[self->state])(self, CONNECT_REQUEST,
@@ -292,7 +295,7 @@
X static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event,
X struct sk_buff *skb, struct irlap_info *info)
X {
- DISCOVERY *discovery_rsp;
+ discovery_t *discovery_rsp;
X int ret = 0;
X
X DEBUG( 4, __FUNCTION__ "()\n");
@@ -304,7 +307,7 @@
X case CONNECT_REQUEST:
X ASSERT( self->irdev != NULL, return -1;);
X
- if ( irda_device_is_media_busy( self->irdev)) {
+ if (irda_device_is_media_busy(self->irdev)) {
X DEBUG( 0, __FUNCTION__
X "(), CONNECT_REQUEST: media busy!\n");
X
@@ -354,7 +357,7 @@
X self->s++;
X
X irlap_start_slot_timer( self, self->slot_timeout);
- irlap_next_state( self, LAP_QUERY);
+ irlap_next_state(self, LAP_QUERY);
X break;
X
X case RECV_DISCOVERY_XID_CMD:
@@ -362,20 +365,20 @@
X
X /* Assert that this is not the final slot */
X if ( info->s <= info->S) {
- self->daddr = info->daddr;
- self->slot = irlap_generate_rand_time_slot( info->S,
- info->s);
+ /* self->daddr = info->daddr; */
+ self->slot = irlap_generate_rand_time_slot(info->S,
+ info->s);
X DEBUG( 4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S,
X info->s, self->slot);
X
X if ( self->slot == info->s) {
X discovery_rsp = irlmp_get_discovery_response();
-
- DEBUG( 4, "Sending XID rsp 1\n");
- irlap_send_discovery_xid_frame( self, info->S,
- self->slot,
- FALSE,
- discovery_rsp);
+ discovery_rsp->daddr = info->daddr;
+
+ irlap_send_discovery_xid_frame(self, info->S,
+ self->slot,
+ FALSE,
+ discovery_rsp);
X self->frame_sent = TRUE;
X } else
X self->frame_sent = FALSE;
@@ -384,11 +387,21 @@
X irlap_next_state( self, LAP_REPLY);
X }
X
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
+ break;
+
+ case RECV_TEST_CMD:
+ skb_pull(skb, sizeof(struct test_frame));
+ irlap_send_test_frame(self, info->daddr, skb);
+ dev_kfree_skb(skb);
+ break;
+ case RECV_TEST_RSP:
+ DEBUG(0, __FUNCTION__ "() not implemented!\n");
+ dev_kfree_skb(skb);
X break;
-
X default:
- /* DEBUG( 0, "irlap_state_ndm: Unknown event"); */
+ DEBUG(2, __FUNCTION__ "(), Unknown event %s",
+ irlap_event[event]);
X ret = -1;
X break;
X }
@@ -414,14 +427,14 @@
X ASSERT( info != NULL, return -1;);
X ASSERT( info->discovery != NULL, return -1;);
X
- DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n",
- info->discovery->daddr);
+ DEBUG(4, __FUNCTION__ "(), daddr=%08x\n",
+ info->discovery->daddr);
X
X hashbin_insert( self->discovery_log,
X (QUEUE *) info->discovery,
X info->discovery->daddr, NULL);
X
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
X
X /* Keep state */
X irlap_next_state( self, LAP_QUERY);
@@ -453,8 +466,8 @@
X }
X break;
X default:
- DEBUG( 4, __FUNCTION__ "(), Unknown event %d, %s\n", event,
- irlap_event[event]);
+ DEBUG(2, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+ irlap_event[event]);
X
X if ( skb != NULL) {
X dev_kfree_skb( skb);
@@ -475,7 +488,7 @@
X static int irlap_state_reply( struct irlap_cb *self, IRLAP_EVENT event,
X struct sk_buff *skb, struct irlap_info *info)
X {
- DISCOVERY *discovery_rsp;
+ discovery_t *discovery_rsp;
X int ret=0;
X
X DEBUG( 4, __FUNCTION__ "()\n");
@@ -503,19 +516,18 @@
X irlap_next_state( self, LAP_NDM);
X
X irlap_discovery_indication( self, info->discovery);
- } else if (( info->s >= self->slot) &&
- ( !self->frame_sent)) {
- DEBUG( 4, "Sending XID rsp 2, s=%d\n", info->s);
+ } else if ((info->s >= self->slot) && (!self->frame_sent)) {
X discovery_rsp = irlmp_get_discovery_response();
+ discovery_rsp->daddr = info->daddr;
X
- irlap_send_discovery_xid_frame( self, info->S,
- self->slot, FALSE,
- discovery_rsp);
+ irlap_send_discovery_xid_frame(self, info->S,
+ self->slot, FALSE,
+ discovery_rsp);
X
X self->frame_sent = TRUE;
- irlap_next_state( self, LAP_REPLY);
+ irlap_next_state(self, LAP_REPLY);
X }
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
X break;
X default:
X DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
@@ -1823,7 +1835,11 @@
X irlap_next_state( self, LAP_NRM_S);
X #endif
X break;
-
+ case RECV_TEST_CMD:
+ skb_pull(skb, sizeof(struct test_frame));
+ irlap_send_test_frame(self, info->daddr, skb);
+ dev_kfree_skb(skb);
+ break;
X default:
X DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n",
X event, irlap_event[event]);
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.2.5/linux/net/irda/irlap_frame.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlap_frame.c Fri Apr 16 08:20:23 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X *
X * Filename: irlap_frame.c
- * Version: 0.8
+ * Version: 0.9
X * Description: Build and transmit IrLAP frames
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Sat Feb 20 01:40:14 1999
+ * Modified at: Tue Apr 6 16:35:21 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, All Rights Resrved.
@@ -22,14 +22,16 @@


X *
X ********************************************************************/
X
-#include <linux/config.h>

X #include <linux/skbuff.h>
-#include <net/sock.h>
-
X #include <linux/if.h>
X #include <linux/if_ether.h>
X #include <linux/netdevice.h>
+#include <linux/irda.h>
+
X #include <net/pkt_sched.h>
+#include <net/sock.h>
+
+#include <asm/byteorder.h>
X
X #include <net/irda/irda.h>
X #include <net/irda/irda_device.h>
@@ -39,8 +41,6 @@
X #include <net/irda/irlap_frame.h>
X #include <net/irda/qos.h>
X
-extern __u8 *irlmp_hint_to_service( __u8 *hint);
-
X /*
X * Function irlap_insert_mtt (self, skb)
X *
@@ -57,6 +57,7 @@
X
X cb = (struct irlap_skb_cb *) skb->cb;
X
+ cb->magic = LAP_MAGIC;
X cb->mtt = self->mtt_required;
X
X /* Reset */
@@ -105,16 +106,11 @@
X void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
X {
X struct sk_buff *skb;
- __u8 *frame;
+ struct snrm_frame *frame;
X int len;
- int n;
-
- DEBUG(4, __FUNCTION__ "()\n");


X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);
-
- n = 0;


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X /* Allocate frame */
X skb = dev_alloc_skb(64);
@@ -122,29 +118,28 @@
X return;
X
X skb_put(skb, 2);
- frame = skb->data;
+ frame = (struct snrm_frame *) skb->data;
X
- /* Insert address field */
- frame[n] = CMD_FRAME;
- frame[n++] |= (qos) ? CBROADCAST : self->caddr;
+ /* Insert connection address field */
+ if (qos)
+ frame->caddr = CMD_FRAME | CBROADCAST;
+ else
+ frame->caddr = CMD_FRAME | self->caddr;
X
X /* Insert control field */
- frame[n++] = SNRM_CMD | PF_BIT;
+ frame->control = SNRM_CMD | PF_BIT;
X
X /*
X * If we are establishing a connection then insert QoS paramerters
X */
X if (qos) {
X skb_put(skb, 9); /* 21 left */
- *((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
- *((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
-
-/* memcpy(frame+n, &self->saddr, 4); n += 4; */
-/* memcpy(frame+n, &self->daddr, 4); n += 4; */
+ frame->saddr = cpu_to_le32(self->saddr);
+ frame->daddr = cpu_to_le32(self->daddr);
X
- frame[n++] = self->caddr;
+ frame->ncaddr = self->caddr;
X
- len = irda_insert_qos_negotiation_params(qos, frame+n);
+ len = irda_insert_qos_negotiation_params(qos, frame->params);
X /* Should not be dangerous to do this afterwards */
X skb_put(skb, len);
X }
@@ -157,26 +152,32 @@
X * Received SNRM (Set Normal Response Mode) command frame
X *
X */
-static void irlap_recv_snrm_cmd( struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info)
+static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info)
X {
X struct snrm_frame *frame;
X
- DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);


+ DEBUG(3, __FUNCTION__ "()\n");

X

- ASSERT( skb != NULL, return;);

- ASSERT( info != NULL, return;);


+ ASSERT(skb != NULL, return;);

+ ASSERT(info != NULL, return;);
X
- frame = ( struct snrm_frame *) skb->data;
+ frame = (struct snrm_frame *) skb->data;
X
X /* Copy peer device address */
- /* memcpy( &info->daddr, &frame->saddr, 4); */
X info->daddr = le32_to_cpu(frame->saddr);
X
X /* Copy connection address */
X info->caddr = frame->ncaddr;
X
- irlap_do_event( self, RECV_SNRM_CMD, skb, info);
+ /* Check if connection address has got a valid value */
+ if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
+ DEBUG(3, __FUNCTION__ "(), invalid connection address!\n");
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ irlap_do_event(self, RECV_SNRM_CMD, skb, info);
X }
X
X /*
@@ -188,8 +189,7 @@
X void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
X {
X struct sk_buff *skb;
- __u8 *frame;
- int n;
+ struct ua_frame *frame;
X int len;
X
X DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
@@ -198,29 +198,25 @@
X ASSERT(self->magic == LAP_MAGIC, return;);
X
X skb = NULL;
- n = 0;
X
X /* Allocate frame */
- skb = dev_alloc_skb(64);
+ skb = dev_alloc_skb(64);
X if (!skb)
X return;
X
X skb_put( skb, 10);
- frame = skb->data;
+ frame = (struct ua_frame *) skb->data;
X
X /* Build UA response */
- frame[n++] = self->caddr;
- frame[n++] = UA_RSP | PF_BIT;
+ frame->caddr = self->caddr;
+ frame->control = UA_RSP | PF_BIT;
X
- *((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
- *((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+ frame->saddr = cpu_to_le32(self->saddr);
+ frame->daddr = cpu_to_le32(self->daddr);
X
-/* memcpy( frame+n, &self->saddr, 4); n += 4; */
-/* memcpy( frame+n, &self->daddr, 4); n += 4; */
-
X /* Should we send QoS negotiation parameters? */
X if (qos) {
- len = irda_insert_qos_negotiation_params(qos, frame+n);
+ len = irda_insert_qos_negotiation_params(qos, frame->params);
X skb_put(skb, len);


X }
X
@@ -239,8 +235,8 @@

X struct sk_buff *skb = NULL;
X __u8 *frame;


X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X skb = dev_alloc_skb(32);
X if (!skb)
@@ -249,7 +245,7 @@
X skb_put( skb, 2);
X frame = skb->data;
X
- if ( self->state == LAP_NDM)
+ if (self->state == LAP_NDM)
X frame[0] = CBROADCAST;
X else
X frame[0] = self->caddr;
@@ -294,8 +290,8 @@
X * Build and transmit a XID (eXchange station IDentifier) discovery
X * frame.
X */
-void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s,
- __u8 command, DISCOVERY *discovery)
+void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
+ __u8 command, discovery_t *discovery)
X {
X struct sk_buff *skb = NULL;
X struct xid_frame *frame;
@@ -311,8 +307,8 @@
X if (!skb)
X return;
X
- skb_put( skb, 14);
- frame = ( struct xid_frame *) skb->data;
+ skb_put(skb, 14);
+ frame = (struct xid_frame *) skb->data;
X
X if ( command) {
X frame->caddr = CBROADCAST | CMD_FRAME;
@@ -324,16 +320,13 @@
X frame->ident = XID_FORMAT;
X
X frame->saddr = cpu_to_le32(self->saddr);
-/* memcpy( &frame->saddr, &self->saddr, 4); */
X
- if ( command)
- /* memcpy( &frame->daddr, &bcast, 4); */
+ if (command)
X frame->daddr = cpu_to_le32(bcast);
X else
- /* memcpy( &frame->daddr, &self->daddr, 4); */
- frame->daddr = cpu_to_le32(self->daddr);
+ frame->daddr = cpu_to_le32(discovery->daddr);
X
- switch( S) {
+ switch(S) {
X case 1:
X frame->flags = 0x00;
X break;
@@ -362,15 +355,15 @@
X if ( !command || ( frame->slotnr == 0xff)) {
X int i;
X
- if (discovery->hint[0] & HINT_EXTENSION)
+ if (discovery->hints.byte[0] & HINT_EXTENSION)
X skb_put( skb, 3+discovery->info_len);
X else
X skb_put( skb, 2+discovery->info_len);
X
X i = 0;
- frame->discovery_info[i++] = discovery->hint[0];
- if( discovery->hint[0] & HINT_EXTENSION)
- frame->discovery_info[i++] = discovery->hint[1];
+ frame->discovery_info[i++] = discovery->hints.byte[0];
+ if(discovery->hints.byte[0] & HINT_EXTENSION)
+ frame->discovery_info[i++] = discovery->hints.byte[1];
X
X frame->discovery_info[i++] = discovery->charset;
X
@@ -391,47 +384,48 @@
X * Received a XID discovery response
X *
X */
-static void irlap_recv_discovery_xid_rsp( struct irlap_cb *self,
- struct sk_buff *skb,
- struct irlap_info *info)
+static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ struct sk_buff *skb,
+ struct irlap_info *info)
X {
X struct xid_frame *xid;
- DISCOVERY *discovery = NULL;
+ discovery_t *discovery = NULL;
X char *text;
X
- DEBUG( 4, __FUNCTION__ "()\n");


+ DEBUG(4, __FUNCTION__ "()\n");

X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);


- ASSERT( skb != NULL, return;);

- ASSERT( info != NULL, return;);


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LAP_MAGIC, return;);


+ ASSERT(skb != NULL, return;);

+ ASSERT(info != NULL, return;);
X
- if (( discovery = kmalloc( sizeof( DISCOVERY), GFP_ATOMIC)) == NULL) {
- DEBUG( 0, __FUNCTION__ "(), kmalloc failed!\n");
+ if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
+ DEBUG(0, __FUNCTION__ "(), kmalloc failed!\n");
X return;
X }
- memset( discovery, 0, sizeof( DISCOVERY));
+ memset(discovery, 0, sizeof(discovery_t));
X
X xid = (struct xid_frame *) skb->data;
X
X /*
X * Copy peer device address and set the source address
X */
- memcpy( &info->daddr, &xid->saddr, 4);
+ info->daddr = le32_to_cpu(xid->saddr);
X discovery->daddr = info->daddr;
X discovery->saddr = self->saddr;
+ discovery->timestamp = jiffies;
X
- DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
+ DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
X
X /* Get info returned from peer */
- discovery->hint[0] = xid->discovery_info[0];
- if ( xid->discovery_info[0] & HINT_EXTENSION) {
- DEBUG( 4, "EXTENSION\n");
- discovery->hint[1] = xid->discovery_info[1];
+ discovery->hints.byte[0] = xid->discovery_info[0];
+ if (xid->discovery_info[0] & HINT_EXTENSION) {
+ DEBUG(4, "EXTENSION\n");
+ discovery->hints.byte[1] = xid->discovery_info[1];
X discovery->charset = xid->discovery_info[2];
X text = (char *) &xid->discovery_info[3];
X } else {
- discovery->hint[1] = 0;
+ discovery->hints.byte[1] = 0;
X discovery->charset = xid->discovery_info[1];
X text = (char *) &xid->discovery_info[2];
X }
@@ -440,11 +434,11 @@
X * FCS bytes resides.
X */
X skb->data[skb->len] = '\0';
- strcpy( discovery->info, text);
+ strcpy(discovery->info, text);
X
X info->discovery = discovery;
X
- irlap_do_event( self, RECV_DISCOVERY_XID_RSP, skb, info);
+ irlap_do_event(self, RECV_DISCOVERY_XID_RSP, skb, info);
X }
X
X /*
@@ -458,7 +452,7 @@
X struct irlap_info *info)
X {
X struct xid_frame *xid;
- DISCOVERY *discovery = NULL;
+ discovery_t *discovery = NULL;
X char *text;
X
X DEBUG( 4, __FUNCTION__ "()\n");
@@ -471,7 +465,6 @@
X xid = (struct xid_frame *) skb->data;
X
X /* Copy peer device address */
- /* memcpy( &info->daddr, &xid->saddr, 4); */
X info->daddr = le32_to_cpu(xid->saddr);
X
X switch ( xid->flags & 0x03) {
@@ -500,25 +493,24 @@
X /*
X * We now have some discovery info to deliver!
X */
- discovery = kmalloc( sizeof( DISCOVERY), GFP_ATOMIC);
- if ( !discovery) {
- DEBUG( 0, __FUNCTION__ "(), kmalloc failed!\n");
+ discovery = kmalloc( sizeof(discovery_t), GFP_ATOMIC);
+ if (!discovery)
X return;
- }
+
X discovery->daddr = info->daddr;
X discovery->saddr = self->saddr;
+ discovery->timestamp = jiffies;
X
X DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n",
X discovery->daddr);
X
- discovery->hint[0] = xid->discovery_info[0];
+ discovery->hints.byte[0] = xid->discovery_info[0];
X if ( xid->discovery_info[0] & HINT_EXTENSION) {
- DEBUG( 4, "EXTENSION\n");
- discovery->hint[1] = xid->discovery_info[1];
+ discovery->hints.byte[1] = xid->discovery_info[1];
X discovery->charset = xid->discovery_info[2];
X text = (char *) &xid->discovery_info[3];
X } else {
- discovery->hint[1] = 0;
+ discovery->hints.byte[1] = 0;
X discovery->charset = xid->discovery_info[1];
X text = (char *) &xid->discovery_info[2];
X }
@@ -533,9 +525,6 @@
X } else
X info->discovery = NULL;
X
- DEBUG( 4, __FUNCTION__"(), s=%d, S=%d <%ld>\n",
- info->s, info->S, jiffies);
-
X irlap_do_event( self, RECV_DISCOVERY_XID_CMD, skb, info);
X }
X
@@ -553,23 +542,11 @@


X ASSERT( self != NULL, return;);

X ASSERT( self->magic == LAP_MAGIC, return;);
X
-#ifdef CONFIG_IRDA_RECYCLE_RR
- if ( self->recycle_rr_skb) {
- DEBUG( 4, __FUNCTION__ "(), recycling skb!\n");
- skb = self->recycle_rr_skb;
- self->recycle_rr_skb = NULL;
- }
-#endif
- if (!skb) {
- skb = dev_alloc_skb( 32);
- if (!skb)
- return;
-
- skb_put( skb, 2);
- }
- ASSERT( skb->len == 2, return;);
-
- frame = skb->data;
+ skb = dev_alloc_skb(32);
+ if (!skb)
+ return;
+
+ frame = skb_put(skb, 2);
X
X frame[0] = self->caddr;
X frame[0] |= (command) ? CMD_FRAME : 0;
@@ -584,18 +561,16 @@
X /*
X * Function irlap_recv_rr_frame (skb, info)
X *
- * Received RR (Receive Ready) frame from peer station
- *
- */
-static void irlap_recv_rr_frame( struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
+ * Received RR (Receive Ready) frame from peer station, no harm in
+ * making it inline since its called only from one single place
+ * (irlap_input).
+ */
+static inline void irlap_recv_rr_frame(struct irlap_cb *self,
+ struct sk_buff *skb,
+ struct irlap_info *info, int command)
X {
X __u8 *frame;


X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);


- ASSERT( skb != NULL, return;);

-
X frame = skb->data;
X info->nr = frame[1] >> 5;
X
@@ -609,32 +584,18 @@
X * until it is outside a frame.
X */
X #if 0
- if (( self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) {
- DEBUG( 0, __FUNCTION__ "(), Wrong state, dropping frame!\n");
- dev_kfree_skb( skb);
+ if ((self->state != LAP_NRM_P) && (self->state != LAP_NRM_S)) {
+ DEBUG(0, __FUNCTION__ "(), Wrong state, dropping frame!\n");
+ dev_kfree_skb(skb);
X return;
X }
X #endif
X
-#ifdef CONFIG_IRDA_RECYCLE_RR
- /* Only recycle one RR frame */
- if ( self->recycle_rr_skb == NULL) {
-
- /* Keep this skb, so it can be reused */
- self->recycle_rr_skb = skb;
-
- /*
- * Set skb to NULL, so that the state machine will not
- * try to deallocate it.
- */
- skb = NULL;
- }
-#endif
X /* Check if this is a command or a response frame */
- if ( command)
- irlap_do_event( self, RECV_RR_CMD, skb, info);
+ if (command)
+ irlap_do_event(self, RECV_RR_CMD, skb, info);
X else
- irlap_do_event( self, RECV_RR_RSP, skb, info);
+ irlap_do_event(self, RECV_RR_RSP, skb, info);
X }
X
X void irlap_send_frmr_frame( struct irlap_cb *self, int command)
@@ -847,8 +808,8 @@
X * Send I(nformation) frame as secondary with final bit set
X *
X */
-void irlap_send_data_secondary_final( struct irlap_cb *self,
- struct sk_buff *skb)
+void irlap_send_data_secondary_final(struct irlap_cb *self,

+ struct sk_buff *skb)
X {

X struct sk_buff *tx_skb = NULL;
X
@@ -965,8 +926,7 @@


X ASSERT( self != NULL, return;);

X ASSERT( self->magic == LAP_MAGIC, return;);
X
- DEBUG( 4, __FUNCTION__ "(), retry_count=%d\n",
- self->retry_count);
+ DEBUG( 4, __FUNCTION__ "(), retry_count=%d\n", self->retry_count);
X
X /* Initialize variables */
X skb = tx_skb = NULL;
@@ -1054,8 +1014,8 @@
X * Contruct and transmit an Unnumbered Information (UI) frame
X *
X */
-void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb,
- int command)
+void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+ int command)
X {
X __u8 *frame;
X
@@ -1079,8 +1039,8 @@
X *
X * Contruct and transmit Information (I) frame
X */
-void irlap_send_i_frame( struct irlap_cb *self, struct sk_buff *skb,
- int command)
+void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
+ int command)
X {
X __u8 *frame;
X
@@ -1096,37 +1056,22 @@
X
X /* Insert next to receive (Vr) */
X frame[1] |= (self->vr << 5); /* insert nr */
-#if 0
- {
- int vr, vs, pf;
-
- /* Chech contents of various fields */
- vr = frame[1] >> 5;
- vs = (frame[1] >> 1) & 0x07;
- pf = (frame[1] >> 4) & 0x01;
-
- DEBUG(0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n",
- vs, vr, pf, jiffies);
- }
-#endif
+
X irlap_queue_xmit(self, skb);
X }
X
X /*
X * Function irlap_recv_i_frame (skb, frame)
X *
- * Receive and parse an I (Information) frame
- *
+ * Receive and parse an I (Information) frame, no harm in making it inline
+ * since it's called only from one single place (irlap_input).
X */
-static void irlap_recv_i_frame( struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
+static inline void irlap_recv_i_frame(struct irlap_cb *self,
+ struct sk_buff *skb,
+ struct irlap_info *info, int command)
X {
X __u8 *frame;


X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LAP_MAGIC, return;);


- ASSERT( skb != NULL, return;);

-
X frame = skb->data;
X
X info->nr = frame[1] >> 5; /* Next to receive */
@@ -1143,17 +1088,17 @@
X * it is receiving frames until the frame is delivered instead of
X * until it is outside a frame.
X */
- if (( self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) {
- DEBUG( 0, __FUNCTION__ "(), Wrong state, dropping frame!\n");
- dev_kfree_skb( skb);
+ if ((self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) {
+ DEBUG(0, __FUNCTION__ "(), Wrong state, dropping frame!\n");
+ dev_kfree_skb(skb);
X return;
X }
X
X /* Check if this is a command or a response frame */
- if ( command)
- irlap_do_event( self, RECV_I_CMD, skb, info);
+ if (command)
+ irlap_do_event(self, RECV_I_CMD, skb, info);
X else
- irlap_do_event( self, RECV_I_RSP, skb, info);
+ irlap_do_event(self, RECV_I_RSP, skb, info);
X }
X
X /*
@@ -1227,22 +1172,94 @@
X }
X
X /*
- * Function irlap_input (skb)
+ * Function irlap_send_test_frame (self, daddr)
+ *
+ * Send a test frame response
+ *
+ */
+void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr,
+ struct sk_buff *cmd)


+{
+ struct sk_buff *skb;

+ struct test_frame *frame;
+
+ skb = dev_alloc_skb(32);
+ if (!skb)
+ return;
+
+ skb_put(skb, sizeof(struct test_frame));
+
+ frame = (struct test_frame *) skb->data;
+
+ /* Build header */
+ if (self->state == LAP_NDM)
+ frame->caddr = CBROADCAST; /* Send response */
+ else
+ frame->caddr = self->caddr;
+
+ frame->control = TEST_RSP;
+
+ /* Insert the swapped addresses */
+ frame->saddr = cpu_to_le32(self->saddr);
+ frame->daddr = cpu_to_le32(daddr);
+
+ /* Copy info */
+ skb_put(skb, cmd->len);
+ memcpy(frame->info, cmd->data, cmd->len);
+
+ /* Return to sender */
+ irlap_wait_min_turn_around(self, &self->qos_tx);
+ irlap_queue_xmit(self, skb);
+}
+
+/*
+ * Function irlap_recv_test_frame (self, skb)
+ *
+ * Receive a test frame
X *
- * Called when a frame is received. Dispatches the right receive function
- * for processing of the frame.
X */
-int irlap_input( struct sk_buff *skb, struct device *netdev,
- struct packet_type *ptype)
+void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info, int command)
+{
+ struct test_frame *frame;
+
+ DEBUG(0, __FUNCTION__ "()\n");
+
+ if (skb->len < sizeof(struct test_frame)) {
+ DEBUG(0, __FUNCTION__ "() test frame to short!\n");
+ return;
+ }
+
+ frame = (struct test_frame *) skb->data;
+
+ /* Read and swap addresses */
+ info->daddr = le32_to_cpu(frame->saddr);
+ info->saddr = le32_to_cpu(frame->daddr);
+
+ if (command)
+ irlap_do_event(self, RECV_TEST_CMD, skb, info);
+ else
+ irlap_do_event(self, RECV_TEST_RSP, skb, info);
+}
+
+/*
+ * Function irlap_driver_rcv (skb, netdev, ptype)
+ *
+ * Called when a frame is received. Dispatches the right receive function
+ * for processing of the frame.
+ *
+ */
+int irlap_driver_rcv(struct sk_buff *skb, struct device *dev,
+ struct packet_type *ptype)
X {
X struct irlap_info info;
X struct irlap_cb *self;
X struct irda_device *idev;
X __u8 *frame;
- int i, command;
+ int command;
X __u8 control;
X
- idev = ( struct irda_device *) netdev->priv;
+ idev = (struct irda_device *) dev->priv;
X
X ASSERT( idev != NULL, return -1;);
X self = idev->irlap;
@@ -1264,24 +1281,18 @@
X /*
X * First check if this frame addressed to us
X */
- if (( info.caddr != self->caddr) && ( info.caddr != CBROADCAST)) {
-
- DEBUG( 0, __FUNCTION__ "(), Received frame is not for us!\n");
- for(i=0; i<(skb->len < 15?skb->len:15);i++) {
- printk( "%02x ", frame[i]);


- }
- printk("\n");
-

- dev_kfree_skb( skb);
+ if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
+ DEBUG(2, __FUNCTION__ "(), Received frame is not for us!\n");
X
+ dev_kfree_skb(skb);
X return 0;
X }
X /*
X * Optimize for the common case and check if the frame is an
X * I(nformation) frame. Only I-frames have bit 0 set to 0
X */
- if( ~control & 0x01) {
- irlap_recv_i_frame( self, skb, &info, command);
+ if(~control & 0x01) {
+ irlap_recv_i_frame(self, skb, &info, command);
X self->stats.rx_packets++;
X return 0;
X }
@@ -1289,19 +1300,17 @@
X * We now check is the frame is an S(upervisory) frame. Only
X * S-frames have bit 0 set to 1 and bit 1 set to 0
X */
- if ( ~control & 0x02) {
+ if (~control & 0x02) {
X /*
X * Received S(upervisory) frame, check which frame type it is
X * only the first nibble is of interest
X */
- switch( control & 0x0f) {
+ switch(control & 0x0f) {
X case RR:
X irlap_recv_rr_frame( self, skb, &info, command);
X self->stats.rx_packets++;
X break;
X case RNR:
- DEBUG( 4, "*** RNR frame received! pf = %d ***\n",
- info.pf >> 4);
X irlap_recv_rnr_frame( self, skb, &info);
X self->stats.rx_packets++;
X break;
@@ -1321,37 +1330,32 @@
X /*
X * This must be a C(ontrol) frame
X */
- switch( control) {
+ switch(control) {
X case XID_RSP:
- DEBUG( 4, "XID rsp frame received!\n");
- irlap_recv_discovery_xid_rsp( self, skb, &info);
+ irlap_recv_discovery_xid_rsp(self, skb, &info);
X break;
X case XID_CMD:
- DEBUG( 4, "XID cmd frame received!\n");
- irlap_recv_discovery_xid_cmd( self, skb, &info);
+ irlap_recv_discovery_xid_cmd(self, skb, &info);
X break;
X case SNRM_CMD:
- DEBUG( 4, "SNRM frame received!\n");
- irlap_recv_snrm_cmd( self, skb, &info);
+ irlap_recv_snrm_cmd(self, skb, &info);
X break;
X case DM_RSP:
X DEBUG( 0, "DM rsp frame received!\n");
- irlap_next_state( self, LAP_NDM);
+ irlap_next_state(self, LAP_NDM);
X break;
X case DISC_CMD:
- DEBUG( 2, "DISC cmd frame received!\n");
- irlap_do_event( self, RECV_DISC_FRAME, skb, &info);
+ irlap_do_event(self, RECV_DISC_FRAME, skb, &info);
X break;
X case TEST_CMD:
- DEBUG( 0, "Test frame received!\n");
- dev_kfree_skb( skb);
+ DEBUG(0,__FUNCTION__ "(), TEST_FRAME\n");
+ irlap_recv_test_frame(self, skb, &info, command);
X break;
X case UA_RSP:
X DEBUG( 4, "UA rsp frame received!\n");
X irlap_recv_ua_frame( self, skb, &info);
X break;
X case FRMR_RSP:
- DEBUG( 4, "FRMR_RSP recevied!\n");
X irlap_recv_frmr_frame( self, skb, &info);
X break;
X case UI_FRAME:
diff -u --recursive --new-file v2.2.5/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.2.5/linux/net/irda/irlmp.c Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlmp.c Thu Apr 15 05:42:42 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X *
X * Filename: irlmp.c
- * Version: 0.8
+ * Version: 0.9
X * Description: IrDA Link Management Protocol (LMP) layer
- * Status: Experimental.
+ * Status: Stable.


X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Sun Aug 17 20:54:32 1997
- * Modified at: Sat Feb 20 01:28:39 1999
+ * Modified at: Wed Apr 7 17:31:48 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,
@@ -30,6 +30,9 @@
X #include <linux/types.h>


X #include <linux/proc_fs.h>
X #include <linux/init.h>

+#include <linux/kmod.h>
+#include <linux/random.h>
+#include <linux/irda.h>
X
X #include <net/irda/irda.h>
X #include <net/irda/irmod.h>
@@ -39,14 +42,13 @@
X #include <net/irda/iriap.h>
X #include <net/irda/irlmp.h>
X #include <net/irda/irlmp_frame.h>
-#include <linux/kmod.h>
X
X /* Master structure */
X struct irlmp_cb *irlmp = NULL;
X
X /* These can be altered by the sysctl interface */
-int sysctl_discovery = 0;
-int sysctl_discovery_slots = 6;
+int sysctl_discovery = 0;
+int sysctl_discovery_slots = 6;
X char sysctl_devname[65];
X
X char *lmp_reasons[] = {
@@ -61,8 +63,7 @@
X
X __u8 *irlmp_hint_to_service( __u8 *hint);
X #ifdef CONFIG_PROC_FS
-int irlmp_proc_read( char *buf, char **start, off_t offset, int len,
- int unused);
+int irlmp_proc_read(char *buf, char **start, off_t offst, int len, int unused);


X #endif
X
X /*

@@ -83,19 +84,21 @@
X
X irlmp->magic = LMP_MAGIC;
X
- irlmp->registry = hashbin_new( HB_LOCAL);
- irlmp->links = hashbin_new( HB_LOCAL);
- irlmp->unconnected_lsaps = hashbin_new( HB_GLOBAL);
+ irlmp->clients = hashbin_new(HB_GLOBAL);
+ irlmp->services = hashbin_new(HB_GLOBAL);
+ irlmp->links = hashbin_new(HB_GLOBAL);
+ irlmp->unconnected_lsaps = hashbin_new(HB_GLOBAL);
+ irlmp->cachelog = hashbin_new(HB_GLOBAL);
X
X irlmp->free_lsap_sel = 0x10; /* Servers use 0x00-0x0f */
X #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
X irlmp->cache.valid = FALSE;
X #endif
- strcpy( sysctl_devname, "Linux");
+ strcpy(sysctl_devname, "Linux");
X
X /* Do discovery every 3 seconds */
- init_timer( &irlmp->discovery_timer);
- irlmp_start_discovery_timer( irlmp, 600);
+ init_timer(&irlmp->discovery_timer);
+ irlmp_start_discovery_timer(irlmp, 600);

X
X return 0;
X }

@@ -109,18 +112,19 @@
X void irlmp_cleanup(void)
X {
X /* Check for main structure */
- ASSERT( irlmp != NULL, return;);
- ASSERT( irlmp->magic == LMP_MAGIC, return;);
+ ASSERT(irlmp != NULL, return;);
+ ASSERT(irlmp->magic == LMP_MAGIC, return;);
X
- del_timer( &irlmp->discovery_timer);
+ del_timer(&irlmp->discovery_timer);
X
- /* FIXME, we need a special function to deallocate LAPs */
- hashbin_delete( irlmp->links, (FREE_FUNC) kfree);
- hashbin_delete( irlmp->unconnected_lsaps, (FREE_FUNC) kfree);
- hashbin_delete( irlmp->registry, (FREE_FUNC) kfree);
+ hashbin_delete(irlmp->links, (FREE_FUNC) kfree);
+ hashbin_delete(irlmp->unconnected_lsaps, (FREE_FUNC) kfree);
+ hashbin_delete(irlmp->clients, (FREE_FUNC) kfree);
+ hashbin_delete(irlmp->services, (FREE_FUNC) kfree);
+ hashbin_delete(irlmp->cachelog, (FREE_FUNC) kfree);
X
X /* De-allocate main structure */
- kfree( irlmp);
+ kfree(irlmp);
X irlmp = NULL;
X }
X
@@ -130,20 +134,20 @@
X * Register with IrLMP and create a local LSAP,
X * returns handle to LSAP.
X */
-struct lsap_cb *irlmp_open_lsap( __u8 slsap_sel, struct notify_t *notify)
+struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, struct notify_t *notify)
X {
X struct lsap_cb *self;
X
- ASSERT( notify != NULL, return NULL;);
- ASSERT( irlmp != NULL, return NULL;);
- ASSERT( irlmp->magic == LMP_MAGIC, return NULL;);
+ ASSERT(notify != NULL, return NULL;);
+ ASSERT(irlmp != NULL, return NULL;);
+ ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
X
- DEBUG( 4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
+ DEBUG(4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
X
X /*
X * Does the client care which Source LSAP selector it gets?
X */
- if ( slsap_sel == LSAP_ANY) {
+ if (slsap_sel == LSAP_ANY) {
X /*
X * Find unused LSAP
X */
@@ -155,41 +159,39 @@
X * Client wants specific LSAP, so check if it's already
X * in use
X */
- if ( irlmp_slsap_inuse( slsap_sel)) {
+ if (irlmp_slsap_inuse(slsap_sel)) {
X return NULL;
X }
- if ( slsap_sel > irlmp->free_lsap_sel)
- irlmp->free_lsap_sel = slsap_sel+1;
X }
X
X /*
X * Allocate new instance of a LSAP connection
X */
- self = kmalloc( sizeof(struct lsap_cb), GFP_ATOMIC);
- if ( self == NULL) {
+ self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
+ if (self == NULL) {
X printk( KERN_ERR "IrLMP: Can't allocate memory for "
X "LSAP control block!\n");
X return NULL;
X }
- memset( self, 0, sizeof(struct lsap_cb));
+ memset(self, 0, sizeof(struct lsap_cb));
X
X self->magic = LMP_LSAP_MAGIC;
X self->slsap_sel = slsap_sel;
X self->dlsap_sel = LSAP_ANY;
X self->connected = FALSE;
X
- init_timer( &self->watchdog_timer);
+ init_timer(&self->watchdog_timer);
X
- ASSERT( notify->instance != NULL, return NULL;);
+ ASSERT(notify->instance != NULL, return NULL;);
X self->notify = *notify;
X
- irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+ irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
X
X /*
X * Insert into queue of unconnected LSAPs
X */
- hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) self,
- self->slsap_sel, NULL);
+ hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) self, (int) self,
+ NULL);
X
X return self;
X }
@@ -197,65 +199,62 @@
X /*
X * Function irlmp_close_lsap (self)
X *
- * Remove an instance of a LSAP
+ * Remove an instance of LSAP
X */
-static void __irlmp_close_lsap( struct lsap_cb *self)
+static void __irlmp_close_lsap(struct lsap_cb *self)
X {
- DEBUG( 4, __FUNCTION__ "()\n");


+ DEBUG(4, __FUNCTION__ "()\n");

X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LMP_LSAP_MAGIC, return;);


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
X
X /*
X * Set some of the variables to preset values
X */
X self->magic = ~LMP_LSAP_MAGIC;
- del_timer( &self->watchdog_timer); /* Important! */
+ del_timer(&self->watchdog_timer); /* Important! */
X
X #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
- ASSERT( irlmp != NULL, return;);
+ ASSERT(irlmp != NULL, return;);
X irlmp->cache.valid = FALSE;
X #endif
- kfree( self);
+ kfree(self);
X }
X
X /*
X * Function irlmp_close_lsap (self)
X *
- *
+ * Close and remove LSAP
X *
X */
-void irlmp_close_lsap( struct lsap_cb *self)
+void irlmp_close_lsap(struct lsap_cb *self)
X {
X struct lap_cb *lap;
- struct lsap_cb *lsap;
+ struct lsap_cb *lsap = NULL;


X
- ASSERT( self != NULL, return;);

- ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
-
- lap = self->lap;


+ ASSERT(self != NULL, return;);

+ ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
X
X /*
X * Find out if we should remove this LSAP from a link or from the
X * list of unconnected lsaps (not associated with a link)
X */
- if ( lap == NULL) {
- lsap = hashbin_remove( irlmp->unconnected_lsaps,
- self->slsap_sel, NULL);
- } else {
- ASSERT( lap != NULL, return;);
- ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
-
- lsap = hashbin_remove( lap->lsaps, self->slsap_sel, NULL);
+ lap = self->lap;
+ if (lap) {
+ ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
+ }
+ /* Check if we found the LSAP! If not then try the unconnected lsaps */
+ if (!lsap) {
+ lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
+ NULL);
X }
- if ( lsap == NULL) {
- DEBUG( 1, __FUNCTION__
+ if (!lsap) {
+ DEBUG(0, __FUNCTION__
X "(), Looks like somebody has removed me already!\n");
X return;
X }
- ASSERT( lsap == self, return;);
-
- __irlmp_close_lsap( self);
+ __irlmp_close_lsap(self);
X }
X
X /*
@@ -265,50 +264,47 @@
X * instances of the IrLAP layer, each connected to different IrDA ports
X *
X */
-void irlmp_register_irlap( struct irlap_cb *irlap, __u32 saddr,
- struct notify_t *notify)
+void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr,
+ struct notify_t *notify)
X {
X struct lap_cb *lap;
X
- DEBUG( 4, __FUNCTION__ "(), Registered IrLAP, saddr = %08x\n",
- saddr);
+ DEBUG(4, __FUNCTION__ "(), Registered IrLAP, saddr = %08x\n", saddr);
X
- ASSERT( irlmp != NULL, return;);
- ASSERT( irlmp->magic == LMP_MAGIC, return;);
- ASSERT( notify != NULL, return;);
+ ASSERT(irlmp != NULL, return;);
+ ASSERT(irlmp->magic == LMP_MAGIC, return;);
+ ASSERT(notify != NULL, return;);
X
X /*
X * Allocate new instance of a LSAP connection
X */
- lap = kmalloc( sizeof(struct lap_cb), GFP_KERNEL);
- if ( lap == NULL) {
- printk( KERN_ERR "IrLMP: Can't allocate memory for "
- "LAP control block!\n");
+ lap = kmalloc(sizeof(struct lap_cb), GFP_KERNEL);
+ if (lap == NULL) {
+ DEBUG(3, __FUNCTION__ "(), unable to kmalloc\n");
X return;
X }
- memset( lap, 0, sizeof(struct lap_cb));
+ memset(lap, 0, sizeof(struct lap_cb));
X
X lap->irlap = irlap;
X lap->magic = LMP_LAP_MAGIC;
X lap->saddr = saddr;
X lap->daddr = DEV_ADDR_ANY;
- lap->lsaps = hashbin_new( HB_GLOBAL);
- lap->cachelog = hashbin_new( HB_LOCAL);
+ lap->lsaps = hashbin_new(HB_GLOBAL);
X
- irlmp_next_lap_state( lap, LAP_STANDBY);
+ irlmp_next_lap_state(lap, LAP_STANDBY);
X
X init_timer(&lap->idle_timer);
X
X /*
X * Insert into queue of unconnected LSAPs
X */
- hashbin_insert( irlmp->links, (QUEUE *) lap, lap->saddr, NULL);
+ hashbin_insert(irlmp->links, (QUEUE *) lap, lap->saddr, NULL);
X
X /*
X * We set only this variable so IrLAP can tell us on which link the
X * different events happened on
X */
- irda_notify_init( notify);
+ irda_notify_init(notify);
X notify->instance = lap;
X }
X
@@ -318,71 +314,24 @@
X * IrLAP layer has been removed!
X *
X */
-void irlmp_unregister_irlap(__u32 saddr)
+void irlmp_unregister_link(__u32 saddr)
X {
- struct lap_cb *self;
+ struct lap_cb *link;
X
X DEBUG(4, __FUNCTION__ "()\n");
X
- self = hashbin_remove(irlmp->links, saddr, NULL);
- if (self) {
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
-
- del_timer(&self->idle_timer);
-
- self->magic = 0;
- kfree(self);
- } else {
- DEBUG(1, __FUNCTION__ "(), Didn't find LAP layer!\n");
- }
-}
-
-void dump_discoveries( hashbin_t *log)
-{
- DISCOVERY *d;
-
- ASSERT( log != NULL, return;);
-
- d = (DISCOVERY *) hashbin_get_first( log);
- while( d != NULL) {


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 31'
echo 'File patch-2.2.6 is continued in part 32'
echo 32 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part33

#!/bin/sh
# this is part 33 of a 34 - part archive


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

if test "$Scheck" != 33; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&
X }
X

X /*
diff -u --recursive --new-file v2.2.5/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.2.5/linux/net/irda/irmod.c Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irmod.c Thu Apr 15 05:42:42 1999


@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Mon Dec 15 13:55:39 1997
- * Modified at: Thu Feb 18 08:51:50 1999
+ * Modified at: Mon Mar 29 09:06:52 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -62,7 +62,6 @@
X extern void irda_proto_cleanup(void);
X
X extern int irda_device_init(void);
-extern int irobex_init(void);
X extern int irlan_init(void);
X extern int irlan_client_init(void);
X extern int irlan_server_init(void);
@@ -71,6 +70,12 @@
X extern int irlpt_client_init(void);
X extern int irlpt_server_init(void);
X
+#ifdef CONFIG_IRDA_COMPRESSION
+#ifdef CONFIG_IRDA_DEFLATE
+extern irda_deflate_init();
+#endif /* CONFIG_IRDA_DEFLATE */
+#endif /* CONFIG_IRDA_COMPRESSION */
+
X static int irda_open(struct inode * inode, struct file *file);
X static int irda_ioctl(struct inode *inode, struct file *filp,
X unsigned int cmd, unsigned long arg);
@@ -132,8 +137,12 @@
X
X /* IrLMP */
X EXPORT_SYMBOL(irlmp_discovery_request);
-EXPORT_SYMBOL(irlmp_register_layer);
-EXPORT_SYMBOL(irlmp_unregister_layer);
+EXPORT_SYMBOL(irlmp_register_client);
+EXPORT_SYMBOL(irlmp_unregister_client);
+EXPORT_SYMBOL(irlmp_update_client);
+EXPORT_SYMBOL(irlmp_register_service);
+EXPORT_SYMBOL(irlmp_unregister_service);
+EXPORT_SYMBOL(irlmp_service_to_hint);
X EXPORT_SYMBOL(irlmp_data_request);
X EXPORT_SYMBOL(irlmp_open_lsap);
X EXPORT_SYMBOL(irlmp_close_lsap);
@@ -179,7 +188,7 @@
X
X __initfunc(int irda_init(void))
X {
- printk(KERN_INFO "Linux-2.2 Support for the IrDA (tm) Protocols (Dag Brattli)\n");
+ printk(KERN_INFO "IrDA (tm) Protocols for Linux-2.2 (Dag Brattli)\n");
X
X irlmp_init();
X irlap_init();
@@ -209,9 +218,6 @@
X #ifdef CONFIG_IRLAN
X irlan_init();
X #endif
-#ifdef CONFIG_IROBEX
- irobex_init();
-#endif
X #ifdef CONFIG_IRCOMM
X ircomm_init();
X irvtd_init();
@@ -234,12 +240,7 @@


X return 0;
X }
X

-/*
- * FIXME:
- * This function should have been wrapped with #ifdef MODULE, but then
- * irda_proto_cleanup() must be moved from af_irda.c to this file since
- * that function must also be wrapped if this one is.
- */
+#ifdef MODULE
X void irda_cleanup(void)
X {
X misc_deregister( &irda.dev);
@@ -263,6 +264,7 @@
X /* Remove middle layer */
X irlmp_cleanup();


X }
+#endif /* MODULE */

X
X /*
X * Function irda_lock (lock)
@@ -505,6 +507,20 @@


X return 0;
X }
X

+void irda_mod_inc_use_count(void)
+{
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+}
+
+void irda_mod_dec_use_count(void)
+{
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
X #ifdef MODULE
X #ifdef CONFIG_PROC_FS
X void irda_proc_modcount(struct inode *inode, int fill)
@@ -543,5 +559,4 @@
X {
X irda_proto_cleanup();
X }
-
-#endif
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.5/linux/net/irda/irobex/Config.in linux/net/irda/irobex/Config.in
--- v2.2.5/linux/net/irda/irobex/Config.in Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irobex/Config.in Wed Dec 31 16:00:00 1969
@@ -1,3 +0,0 @@
-
-dep_tristate 'IrOBEX protocol' CONFIG_IROBEX $CONFIG_IRDA
-
diff -u --recursive --new-file v2.2.5/linux/net/irda/irobex/Makefile linux/net/irda/irobex/Makefile
--- v2.2.5/linux/net/irda/irobex/Makefile Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irobex/Makefile Wed Dec 31 16:00:00 1969
@@ -1,19 +0,0 @@
-#
-# Makefile for the Linux IrDA IrOBEX protocol layer.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-#O_TARGET :=
-O_OBJS := irobex.o
-M_OBJS := irobex.o
-
-OX_OBJS +=
-
-include $(TOPDIR)/Rules.make
-
-tar:
- tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.2.5/linux/net/irda/irobex/irobex.c linux/net/irda/irobex/irobex.c
--- v2.2.5/linux/net/irda/irobex/irobex.c Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irobex/irobex.c Wed Dec 31 16:00:00 1969
@@ -1,1170 +0,0 @@
-/*********************************************************************
- *
- * Filename: irobex.c
- * Version: 0.4
- * Description: Kernel side of the IrOBEX layer
- * Status: Experimental.
- * Author: Dag Brattli <da...@cs.uit.no>
- * Created at: Thu Jun 25 21:21:07 1998
- * Modified at: Mon Feb 8 09:05:01 1999
- * Modified by: Dag Brattli <da...@cs.uit.no>
- *
- * Copyright (c) 1998 Dag Brattli, All Rights Reserved.


- *
- * 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.
- *

- * Neither Dag Brattli nor University of Tromsų admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.


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

-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/ioctl.h>
-#include <linux/init.h>
-
-#include <asm/byteorder.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/poll.h>
-
-#include <net/irda/irttp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-
-#include <net/irda/irobex.h>
-
-/*
- * Master structure, only one instance for now!!
- */
-struct irobex_cb *irobex;
-
-extern char *lmp_reasons[];
-
-char *irobex_state[] = {
- "OBEX_IDLE",
- "OBEX_DISCOVER",
- "OBEX_QUERY",
- "OBEX_CONN",
- "OBEX_DATA",
-};
-
-static void irobex_cleanup(void);
-/* static struct irobex_cb *irobex_open(void); */
-/* static void irobex_close( struct irobex_cb *self); */
-
-static void irobex_data_indication( void *instance, void *sap,
- struct sk_buff *skb);
-static void irobex_disconnect_indication( void *instance, void *sap,
- LM_REASON reason,
- struct sk_buff *skb);
-static void irobex_disconnect_request( struct irobex_cb *self);
-static int irobex_connect_request(struct irobex_cb *self);
-static void irobex_connect_confirm( void *instance, void *sap,
- struct qos_info *qos,
- int max_sdu_size, struct sk_buff *skb);
-static void irobex_discovery_indication( DISCOVERY *discovery);
-static void irobex_flow_indication( void *instance, void *sap,
- LOCAL_FLOW flow);
-static void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value,
- void *priv);
-static void irobex_register_server( struct irobex_cb *self);
-static int irobex_ioctl( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-static int irobex_dev_open( struct inode * inode, struct file *file);
-static int irobex_dev_close( struct inode *inode, struct file *file);
-static ssize_t irobex_read( struct file *file, char *buffer, size_t count,
- loff_t *noidea);
-static ssize_t irobex_write( struct file *file, const char *buffer,
- size_t count, loff_t *noidea);
-static loff_t irobex_seek( struct file *, loff_t, int);
-static u_int irobex_poll( struct file *file, poll_table *wait);
-static int irobex_fasync( int, struct file *, int);
-
-static struct file_operations irobex_fops = {
- irobex_seek, /* seek */
- irobex_read,
- irobex_write,
- NULL, /* readdir */
- irobex_poll, /* poll */
- irobex_ioctl, /* ioctl */
- NULL, /* mmap */
- irobex_dev_open,
- NULL,
- irobex_dev_close,
- NULL,
- irobex_fasync,
-};
-
-#ifdef CONFIG_PROC_FS
-static int irobex_proc_read( char *buf, char **start, off_t offset,

- int len, int unused);
-

-extern struct proc_dir_entry proc_irda;
-
-struct proc_dir_entry proc_irobex = {
- 0, 6, "irobex",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL,
- &irobex_proc_read,
-};
-#endif
-
-/*
- * Function irobex_init (dev)
- *
- * Initializes the irobex control structure, and registers as a misc
- * device
- *
- */
-__initfunc(int irobex_init(void))
-{
- struct irmanager_event mgr_event;
- struct irobex_cb *self;
-
- self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);


- if ( self == NULL)

- return -ENOMEM;
-
- memset( self, 0, sizeof(struct irobex_cb));
- sprintf( self->devname, "irobex%d", 0); /* Just one instance for now */
-
- self->magic = IROBEX_MAGIC;
- self->rx_flow = self->tx_flow = FLOW_START;
-
- self->dev.minor = MISC_DYNAMIC_MINOR;
- self->dev.name = "irobex";
- self->dev.fops = &irobex_fops;
-
- skb_queue_head_init( &self->rx_queue);
- init_timer( &self->watchdog_timer);
-
- irobex = self;
-
- misc_register( &self->dev);
-
-#ifdef CONFIG_PROC_FS
- proc_register( &proc_irda, &proc_irobex);
-#endif /* CONFIG_PROC_FS */
-
- irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE,
- irobex_discovery_indication);
-
-/* mgr_event.event = EVENT_IROBEX_INIT; */
-/* sprintf( mgr_event.devname, "%s", self->devname); */
-/* irmanager_notify( &mgr_event); */


-
- return 0;
-}

-
-/*
- * Function irobex_cleanup (void)
- *
- * Removes the IrOBEX layer
- *
- */
-#ifdef MODULE
-static void irobex_cleanup(void)
-{
- struct sk_buff *skb;
- struct irobex_cb *self;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = irobex;
-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- /*
- * Deregister client and server
- */
- irlmp_unregister_layer( S_OBEX, CLIENT | SERVER);
-
- if ( self->tsap) {


- irttp_disconnect_request(self->tsap, NULL, P_NORMAL);

- irttp_close_tsap( self->tsap);


- self->tsap = NULL;
- }

-
- /* Stop timers */
- del_timer( &self->watchdog_timer);
-
- /*
- * Deallocate buffers
- */
- while (( skb = skb_dequeue( &self->rx_queue)) != NULL)
- dev_kfree_skb( skb);
-
-#ifdef CONFIG_PROC_FS
- proc_unregister( &proc_irda, proc_irobex.low_ino);
-#endif
-
- misc_deregister( &self->dev);
-
- kfree( self);
-}
-#endif /* MODULE */
-
-/*
- * Function irobex_read (inode, file, buffer, count)
- *
- * User process wants to read some data
- *
- */
-static ssize_t irobex_read( struct file *file, char *buffer, size_t count,
- loff_t *noidea)
-{
- int len=0;
- struct irobex_cb *self;
- struct sk_buff *skb = NULL;
- int ret;
-
- self = irobex;
-
- ASSERT( self != NULL, return -EIO;);
- ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
-
- DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, state=%s, eof=%d\n",
- count, skb_queue_len( &self->rx_queue),
- irobex_state[self->state], self->eof);
-
- if ( self->state != OBEX_DATA) {
- DEBUG( 0, __FUNCTION__ "(), link not connected yet!\n");
- return -EIO;
- }
-
- /*
- * If there is data to return, then we return it. If not, then we
- * must check if we are still connected
- */
- if ( skb_queue_len( &self->rx_queue) == 0) {
-
- /* Still connected? */
- if ( self->state != OBEX_DATA) {
- switch ( self->eof) {
- case LM_USER_REQUEST:
- self->eof = FALSE;
- DEBUG(3, "read_irobex: returning 0\n");
- ret = 0;
- break;
- case LM_LAP_DISCONNECT:
- self->eof = FALSE;
- ret = -EIO;
- break;
- case LM_LAP_RESET:
- self->eof = FALSE;
- ret = -ECONNRESET;
- break;
- default:
- self->eof = FALSE;
- ret = -EIO;
- break;
- }
- return ret;
- }
-
- /* Return if user does not want to block */
- if ( file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
- /* Go to sleep and wait for data! */
- interruptible_sleep_on( &self->read_wait);
-
- /*
- * Ensure proper reaction to signals, and screen out
- * blocked signals (page 112. linux device drivers)
- */
- if ( signal_pending( current))


- return -ERESTARTSYS;
- }
-

- while ( count && skb_queue_len( &self->rx_queue)) {
-
- skb = skb_dequeue( &self->rx_queue);
-
- /*
- * Check if we have previously stopped IrTTP and we know
- * have more free space in our rx_queue. If so tell IrTTP
- * to start delivering frames again before our rx_queue gets
- * empty
- */
- if ( self->rx_flow == FLOW_STOP) {
- if ( skb_queue_len( &self->rx_queue) < LOW_THRESHOLD) {
- DEBUG( 4, __FUNCTION__ "(), Starting IrTTP\n");
- self->rx_flow = FLOW_START;
- irttp_flow_request( self->tsap, FLOW_START);
- }
- }
-
- /*
- * Is the request from the user less that the amount in the
- * current packet?
- */
- if ( count < skb->len) {
- copy_to_user( buffer+len, skb->data, count);
- len += count;
-
- /*
- * Remove copied data from skb and queue
- * it for next read
- */
- skb_pull( skb, count);
- skb_queue_head( &self->rx_queue, skb);
-
- return len;
- } else {
- copy_to_user( buffer+len, skb->data, skb->len);
- count -= skb->len;
- len += skb->len;
-
- dev_kfree_skb( skb);
- }
- }
- return len;
-}
-
-/*
- * Function irobex_write (inode, file, buffer, count)
- *
- * User process wants to write to device
- *
- */
-static ssize_t irobex_write( struct file *file, const char *buffer,
- size_t count, loff_t *noidea)
-{
- struct irobex_cb *self;
- struct sk_buff *skb;
- int data_len = 0;
- int len = 0;
-
- self = irobex;
-
- ASSERT( self != NULL, return -EIO;);
- ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
-
- DEBUG( 4, __FUNCTION__ ": count = %d\n", count);
-
- /*
- * If we are not connected then we just give up!
- */
- if ( self->state != OBEX_DATA) {
- DEBUG( 0, __FUNCTION__ "(): Not connected!\n");
-
- return -ENOLINK;
- }
-
- /* Check if IrTTP is wants us to slow down */
- if ( self->tx_flow == FLOW_STOP) {
- DEBUG( 4, __FUNCTION__
- "(), IrTTP wants us to slow down, going to sleep\n");
- interruptible_sleep_on( &self->write_wait);
- }
-
- /* Send data to TTP layer possibly as muliple packets */
- while ( count) {
-
- /*
- * Check if request is larger than what fits inside a TTP
- * frame. In that case we must fragment the frame into
- * multiple TTP frames. IrOBEX should not care about message
- * boundaries.
- */
- if ( count < (self->irlap_data_size - IROBEX_MAX_HEADER))
- data_len = count;
- else
- data_len = self->irlap_data_size - IROBEX_MAX_HEADER;
-
- DEBUG( 4, __FUNCTION__ "(), data_len=%d, header_len = %d\n",
- data_len, IROBEX_MAX_HEADER);
-
- skb = dev_alloc_skb( data_len + IROBEX_MAX_HEADER);
- if ( skb == NULL) {
- DEBUG( 0, "irobex - couldn't allocate skbuff!\n");


- return 0;
- }
-

- skb_reserve( skb, IROBEX_MAX_HEADER);
- skb_put( skb, data_len);
-
- copy_from_user( skb->data, buffer+len, data_len);
- len += data_len;
- count -= data_len;
-
- DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int) skb->len);
- ASSERT( skb->len <= (self->irlap_data_size-IROBEX_MAX_HEADER),
- return len;);
-
- irttp_data_request( self->tsap, skb);
- }
- return (len);
-}
-
-/*
- * Function irobex_poll (file, wait)
- *
- *
- *
- */
-static u_int irobex_poll(struct file *file, poll_table *wait)
-{
- DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n");
-
- /* check out /usr/src/pcmcia/modules/ds.c for an example */
- return 0;
-}
-
-/*
- * Function irobex_fasync (inode, filp, mode)
- *
- * Implementation for SIGIO
- *
- */
-static int irobex_fasync( int fd, struct file *filp, int on)
-{
- struct irobex_cb *self;
-


- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = irobex;
-
- ASSERT( self != NULL, return -1;);
- ASSERT( self->magic == IROBEX_MAGIC, return -1;);
-
- return fasync_helper( fd, filp, on, &self->async);
-}
-
-/*
- * Function irobex_seek (inode, file, buffer, count)
- *
- * Not implemented yet!
- *
- */
-static loff_t irobex_seek( struct file *file, loff_t off, int whence)
-{
- DEBUG( 0, __FUNCTION__ "(), Not implemented yet!\n");
-
- return -ESPIPE;
-}
-
-/*
- * Function irobex_ioctl (inode, filp, cmd, arg)
- *
- * Drivers IOCTL handler, used for connecting and disconnecting
- * irobex connections
- *
- */
-static int irobex_ioctl( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- struct irobex_cb *self;
- int err = 0;
- int size = _IOC_SIZE(cmd);
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = irobex;
-
- ASSERT(self != NULL, return -ENOTTY;);
- ASSERT(self->magic == IROBEX_MAGIC, return -ENOTTY;);
-
- if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC)
- return -EINVAL;
- if ( _IOC_NR(cmd) > IROBEX_IOC_MAXNR)
- return -EINVAL;
-
- if ( _IOC_DIR(cmd) & _IOC_READ)
- err = verify_area( VERIFY_WRITE, (void *) arg, size);
- else if ( _IOC_DIR(cmd) & _IOC_WRITE)
- err = verify_area( VERIFY_READ, (void *) arg, size);
- if ( err)
- return err;
-
- switch ( cmd) {
- case IROBEX_IOCSCONNECT:
- DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
- return irobex_connect_request( self);
- break;
- case IROBEX_IOCSDISCONNECT:
- DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
- irobex_disconnect_request( self);
- break;
- default:
- return -EINVAL;


- }
- return 0;
-}

-
-/*
- * Function irobex_dev_open (inode, file)
- *
- * Device opened by user process
- *
- */
-static int irobex_dev_open( struct inode * inode, struct file *file)
-{
- struct irobex_cb *self;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = irobex;
-
- ASSERT( self != NULL, return -1;);
- ASSERT( self->magic == IROBEX_MAGIC, return -1;);
-
- if ( self->count++) {
- DEBUG( 3, "open_irobex: count not zero; actual = %d\n",
- self->count);
- self->count--;


- return -EBUSY;
- }
-

- irobex_register_server( self);
-
- /* Reset values for this instance */
- self->state = OBEX_IDLE;
- self->eof = FALSE;
- self->daddr = 0;
- self->dtsap_sel = 0;
- self->rx_flow = FLOW_START;
- self->tx_flow = FLOW_START;
-
- MOD_INC_USE_COUNT;


-
- return 0;
-}

-
-static int irobex_dev_close( struct inode *inode, struct file *file)
-{
- struct irobex_cb *self;
- struct sk_buff *skb;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = irobex;
-
- ASSERT( self != NULL, return -ENODEV;);
- ASSERT( self->magic == IROBEX_MAGIC, return -EBADR;);
-
- /* Deallocate buffers */
- while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
- DEBUG( 3, "irobex_close: freeing SKB\n");
- dev_kfree_skb( skb);
- }
-
- /* Close TSAP is its still there */
- if ( self->tsap) {


- irttp_disconnect_request(self->tsap, NULL, P_NORMAL);

- irttp_close_tsap( self->tsap);


- self->tsap = NULL;
- }

- self->state = OBEX_IDLE;
- self->eof = FALSE;
- self->daddr = 0;
- self->dtsap_sel = 0;
- self->rx_flow = FLOW_START;
- self->tx_flow = FLOW_START;
-
- /* Remove this filp from the asynchronously notified filp's */
- irobex_fasync( -1, file, 0);
-
- self->count--;
-
- MOD_DEC_USE_COUNT;


-
- return 0;
-}

-
-/*
- * Function irobex_discovery_inication (daddr)
- *
- * Remote device discovered, try query the remote IAS to see which


- * device it is, and which services it has.

- *
- */
-static void irobex_discovery_indication( DISCOVERY *discovery)
-{
- struct irobex_cb *self;
-
- DEBUG( 0, __FUNCTION__ "()\n");
-
- self = irobex;
-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- /* Remember address and time if was discovered */


- self->daddr = discovery->daddr;
- self->saddr = discovery->saddr;

- self->time_discovered = jiffies;
-
- /* Wake up process if its waiting for device to be discovered */
- if ( self->state == OBEX_DISCOVER)
- wake_up_interruptible( &self->write_wait);
-}
-
-static void irobex_disconnect_request( struct irobex_cb *self)
-{
- if ( self->state != OBEX_DATA)
- return;
-
- irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
-
- /* Reset values for this instance */
- self->state = OBEX_IDLE;
- self->eof = LM_USER_REQUEST;
- self->daddr = 0;
- self->dtsap_sel = 0;
- self->rx_flow = FLOW_START;
- self->tx_flow = FLOW_START;
-
- wake_up_interruptible( &self->read_wait);
-}
-
-/*
- * Function irobex_disconnect_indication (handle, reason, priv)
- *
- * Link has been disconnected
- *
- */
-static void irobex_disconnect_indication( void *instance, void *sap,
- LM_REASON reason,
- struct sk_buff *userdata)
-{
- struct irobex_cb *self;
-
- DEBUG( 0, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
-
- self = ( struct irobex_cb *) instance;
-

- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- self->state = OBEX_IDLE;
- self->eof = reason;
- self->daddr = 0;
- self->dtsap_sel = 0;
- self->rx_flow = self->tx_flow = FLOW_START;
-
- wake_up_interruptible( &self->read_wait);
- wake_up_interruptible( &self->write_wait);
-
- DEBUG( 4, __FUNCTION__ "(), skb_queue_len=%d\n",
- skb_queue_len( &irobex->rx_queue));
-
- if ( userdata)
- dev_kfree_skb( userdata);
-}
-
-int irobex_connect_request(struct irobex_cb *self)
-{
- int count = 0;
-
- /* Already connected? */
- if ( self->state == OBEX_DATA) {
- DEBUG( 0, __FUNCTION__ "(), already connected!\n");


- return 0;
- }
-

- /* Timeout after 15 secs. */
- irobex_start_watchdog_timer( self, 1000);
-
- /*
- * If we have discovered a remote device we
- * check if the discovery is still fresh. If not, we don't
- * trust the address.
- */
- if ( self->daddr && ((jiffies - self->time_discovered) > 1000)) {
- DEBUG( 0, __FUNCTION__ "(), daddr is old <%d>!\n",
- jiffies - self->time_discovered);
- self->daddr = 0;
- }
-
- /*
- * Try to discover remote remote device if it has not been
- * discovered yet.
- */
- if ( !self->daddr) {
- self->state = OBEX_DISCOVER;
-
- irlmp_discovery_request( 8);
-
- /* Wait for discovery to complete */
- interruptible_sleep_on( &self->write_wait);
- del_timer( &self->watchdog_timer);
- }
-
- /* Give up if we are unable to discover any remote devices */
- if ( !self->daddr) {
- DEBUG( 0, __FUNCTION__
- "(), Unable to discover any devices!\n");
- return -EHOSTUNREACH;
- }
-
- /* Need to find remote destination TSAP selector? */
- while ( !self->dtsap_sel) {
- DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
-
- self->state = OBEX_QUERY;
-
- /* Timeout after 5 secs. */
- irobex_start_watchdog_timer( self, 500);
- iriap_getvaluebyclass_request(
- "OBEX", "IrDA:TinyTP:LsapSel",


- self->saddr, self->daddr,

- irobex_get_value_confirm,
- self);
-
- interruptible_sleep_on( &self->write_wait);
- del_timer( &self->watchdog_timer);
-
- /* Give up after a few tries */
- if (( count++ > 2) && !self->dtsap_sel) {
- DEBUG( 0, __FUNCTION__
- "(), Unable to query remote LM-IAS!\n");
- return -ETIMEDOUT;
- }
- }
- self->state = OBEX_CONN;
-
- /* Timeout after 5 secs. */
- irobex_start_watchdog_timer( self, 500);
-
- irttp_connect_request( self->tsap, self->dtsap_sel,
- self->saddr, self->daddr, NULL, SAR_DISABLE,
- NULL);
-
- /* Go to sleep and wait for connection! */
- interruptible_sleep_on( &self->write_wait);
- del_timer( &self->watchdog_timer);
-
- if ( self->state != OBEX_DATA) {
- DEBUG( 0, __FUNCTION__
- "(), Unable to connect to remote device!\n");
- return -ETIMEDOUT;


- }
- return 0;
-}

-
-/*
- * Function irobex_connect_confirm (instance, sap, qos, userdata)
- *
- * Connection to peer IrOBEX layer established
- *
- */
-static void irobex_connect_confirm( void *instance, void *sap,
- struct qos_info *qos,
- int max_sdu_size, struct sk_buff *userdata)
-{
- struct irobex_cb *self;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = ( struct irobex_cb *) instance;
-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
- ASSERT( qos != NULL, return;);
-
- DEBUG( 4, __FUNCTION__ "(), IrLAP data size=%d\n",
- qos->data_size.value);
-
- self->irlap_data_size = qos->data_size.value;
-
- /*
- * Wake up any blocked process wanting to write. Finally this process
- * can start writing since the connection is now open :-)
- */
- if (self->state == OBEX_CONN) {
- self->state = OBEX_DATA;
- wake_up_interruptible( &self->write_wait);
- }
-
- if ( userdata) {
- dev_kfree_skb( userdata);


-
- }
-}
-
-/*

- * Function irobex_connect_response (handle)
- *
- * Accept incomming connection
- *
- */
-void irobex_connect_response( struct irobex_cb *self)
-{
- struct sk_buff *skb;
-/* __u8 *frame; */
-


- DEBUG( 4, __FUNCTION__ "()\n");

-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- self->state = OBEX_DATA;
-
- skb = dev_alloc_skb( 64);
- if (skb == NULL) {
- DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n");
- return;
- }
-
- /* Reserve space for MUX_CONTROL and LAP header */
- skb_reserve( skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER);
-
- irttp_connect_response( self->tsap, SAR_DISABLE, skb);
-}
-
-/*
- * Function irobex_connect_indication (handle, skb, priv)
- *
- * Connection request from a remote device
- *
- */
-void irobex_connect_indication( void *instance, void *sap,

- struct qos_info *qos, int max_sdu_size,

- struct sk_buff *userdata)
-{
- struct irmanager_event mgr_event;
- struct irobex_cb *self;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = ( struct irobex_cb *) instance;
-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
- ASSERT( userdata != NULL, return;);
-
- self->eof = FALSE;
-
- DEBUG( 4, __FUNCTION__ "(), skb_len = %d\n",
- (int) userdata->len);
-
- DEBUG( 4, __FUNCTION__ "(), IrLAP data size=%d\n",
- qos->data_size.value);
-
- ASSERT( qos->data_size.value >= 64, return;);
-
- self->irlap_data_size = qos->data_size.value;
-
- /* We just accept the connection */
- irobex_connect_response( self);
-#if 1
- mgr_event.event = EVENT_IROBEX_START;
- sprintf( mgr_event.devname, "%s", self->devname);
- irmanager_notify( &mgr_event);
-#endif
- wake_up_interruptible( &self->read_wait);
-
- if ( userdata) {
- dev_kfree_skb( userdata);
- }
-}
-
-/*
- * Function irobex_data_indication (instance, sap, skb)
- *
- * This function gets the data that is received on the data channel
- *
- */
-static void irobex_data_indication( void *instance, void *sap,
- struct sk_buff *skb)
-{
-
- struct irobex_cb *self;
-
- self = ( struct irobex_cb *) instance;
-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);


- ASSERT( skb != NULL, return;);
-

- DEBUG( 4, __FUNCTION__ "(), len=%d\n", (int) skb->len);
-
- skb_queue_tail( &self->rx_queue, skb);
-
- /*
- * Check if queues are beginning to get filled, and inform
- * IrTTP to slow down if that is the case
- */
- if ( skb_queue_len( &self->rx_queue) > HIGH_THRESHOLD) {
- DEBUG( 0, __FUNCTION__
- "(), rx_queue is full, telling IrTTP to slow down\n");
- self->rx_flow = FLOW_STOP;
- irttp_flow_request( self->tsap, FLOW_STOP);
- }
-
- /*
- * Wake up process blocked on read or select
- */
- wake_up_interruptible( &self->read_wait);
-
- /* Send signal to asynchronous readers */
- if ( self->async)
- kill_fasync( self->async, SIGIO);
-}
-
-/*
- * Function irobex_flow_indication (instance, sap, cmd)
- *
- *
- *
- */
-static void irobex_flow_indication( void *instance, void *sap,
- LOCAL_FLOW flow)
-{
- struct irobex_cb *self;
-


- DEBUG( 4, __FUNCTION__ "()\n");

-
- self = ( struct irobex_cb *) instance;
-

- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- switch ( flow) {
- case FLOW_STOP:
- DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n");
- self->tx_flow = flow;
- break;
- case FLOW_START:
- self->tx_flow = flow;
- DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to start again\n");
- wake_up_interruptible( &self->write_wait);
- break;
- default:
- DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
- }
-}
-
-/*
- * Function irobex_get_value_confirm (obj_id, value)
- *
- * Got results from previous GetValueByClass request
- *
- */
-static void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value,
- void *priv)
-{
- struct irobex_cb *self;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-
- ASSERT( priv != NULL, return;);
- self = ( struct irobex_cb *) priv;
-
- if ( !self || self->magic != IROBEX_MAGIC) {
- DEBUG( 0, __FUNCTION__ "(), bad magic!\n");
- return;
- }
-


- /* Check if request succeeded */
- if ( !value) {
- DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-
- return;
- }
-

- switch ( value->type) {
- case IAS_INTEGER:
- DEBUG( 4, __FUNCTION__ "() int=%d\n", value->t.integer);
-
- if ( value->t.integer != -1) {
- self->dtsap_sel = value->t.integer;
-
- /*
- * Got the remote TSAP, so wake up any processes
- * blocking on write. We don't do the connect
- * ourselves since we must make sure there is a
- * process that wants to make a connection, so we
- * just let that process do the connect itself
- */
- if ( self->state == OBEX_QUERY)
- wake_up_interruptible( &self->write_wait);
- } else
- self->dtsap_sel = 0;
- break;
- case IAS_STRING:
- DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string);
- break;
- case IAS_OCT_SEQ:
- DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n");
- break;
- case IAS_MISSING:
- DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n");
- break;
- default:
- DEBUG( 0, __FUNCTION__ "(), unknown type!\n");


- break;
- }
-}
-

-/*
- * Function irobex_provider_confirm (dlsap)
- *
- * IrOBEX provider is discovered. We can now establish connections
- * TODO: This function is currently not used!
- */
-void irobex_provider_confirm( struct irobex_cb *self, __u8 dlsap)
-{
- /* struct irobex_cb *self = irobex; */


- struct notify_t notify;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- notify.data_indication = irobex_data_indication;
- notify.connect_confirm = irobex_connect_confirm;
- notify.connect_indication = irobex_connect_indication;
- notify.flow_indication = irobex_flow_indication;
- notify.disconnect_indication = irobex_disconnect_indication;


- notify.instance = self;
-

- /* Create TSAP's */
- self->tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT,
- &notify);
-
-/* DEBUG( 0, "OBEX allocated TSAP%d for data\n", self->handle); */
-
- /* irlan_do_event( IAS_PROVIDER_AVAIL, NULL, &frame); */
-}
-
-/*
- * Function irobex_register_server(void)
- *
- * Register server support so we can accept incomming connections. We
- * must register both a TSAP for control and data
- *
- */
-static void irobex_register_server( struct irobex_cb *self)


-{
- struct notify_t notify;

- struct ias_object *obj;
-


- DEBUG( 4, __FUNCTION__ "()\n");

-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- irda_notify_init( &notify);
-
- notify.connect_confirm = irobex_connect_confirm;
- notify.connect_indication = irobex_connect_indication;
- notify.disconnect_indication = irobex_disconnect_indication;
- notify.data_indication = irobex_data_indication;
- notify.flow_indication = irobex_flow_indication;
- notify.instance = self;
- strcpy( notify.name, "IrOBEX");
-
- self->tsap = irttp_open_tsap( TSAP_IROBEX, DEFAULT_INITIAL_CREDIT,
- &notify);
- if ( self->tsap == NULL) {
- DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
- return;
- }
-
- /*

- * Register with LM-IAS
- */

- obj = irias_new_object( "OBEX", 0x42343);
- irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IROBEX);
- irias_insert_object( obj);
-}
-
-void irobex_watchdog_timer_expired( unsigned long data)
-{
- struct irobex_cb *self = ( struct irobex_cb *) data;
-

- DEBUG( 4, __FUNCTION__ "()\n");

-


- ASSERT( self != NULL, return;);

- ASSERT( self->magic == IROBEX_MAGIC, return;);
-
- switch (self->state) {
- case OBEX_CONN: /* FALLTROUGH */
- case OBEX_DISCOVER: /* FALLTROUGH */
- case OBEX_QUERY: /* FALLTROUGH */
- wake_up_interruptible( &self->write_wait);
- break;
- default:


- break;
- }
-}
-

-#ifdef CONFIG_PROC_FS
-/*
- * Function irobex_proc_read (buf, start, offset, len, unused)
- *
- * Give some info to the /proc file system
- */
-static int irobex_proc_read( char *buf, char **start, off_t offset,

- int len, int unused)

-{
- struct irobex_cb *self;
-
- self = irobex;
-
- ASSERT( self != NULL, return -1;);
- ASSERT( self->magic == IROBEX_MAGIC, return -1;);
-
- len = 0;
-
- len += sprintf( buf+len, "ifname: %s ",self->devname);
- len += sprintf( buf+len, "state: %s ", irobex_state[ self->state]);
- len += sprintf( buf+len, "EOF: %s\n", self->eof ? "TRUE": "FALSE");
-
- return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrOBEX module");
-
-/*
- * Function init_module (void)
- *
- * Initialize the IrOBEX module, this function is called by the
- * modprobe(1) program.
- */
-int init_module(void)
-{
- irobex_init();


-
- return 0;
-}

-
-/*
- * Function cleanup_module (void)
- *
- * Remove the IrOBEX module, this function is called by the rmmod(1)
- * program
- */
-void cleanup_module(void)
-{
- /*
- * No need to check MOD_IN_USE, as sys_delete_module() checks.
- */
-
- /* Free some memory */
- irobex_cleanup();
-}
-
-#endif /* MODULE */
-
-
-
-
diff -u --recursive --new-file v2.2.5/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.2.5/linux/net/irda/irproc.c Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irproc.c Thu Apr 15 05:42:42 1999


@@ -1,12 +1,12 @@
X /*********************************************************************
X *

X * Filename: irproc.c
- * Version:
+ * Version: 1.0
X * Description: Various entries in the /proc file system
X * Status: Experimental.
X * Author: Thomas Davis, <rat...@radiks.net>
X * Created at: Sat Feb 21 21:33:24 1998
- * Modified at: Thu Feb 11 15:23:23 1999
+ * Modified at: Tue Apr 6 19:07:06 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>,
@@ -27,6 +27,7 @@
X #include <linux/miscdevice.h>
X #include <linux/proc_fs.h>
X
+#include <net/irda/irda.h>
X #include <net/irda/irmod.h>
X #include <net/irda/irlap.h>
X #include <net/irda/irlmp.h>
@@ -46,6 +47,8 @@
X int unused);
X extern int irias_proc_read(char *buf, char **start, off_t offset, int len,
X int unused);
+extern int discovery_proc_read(char *buf, char **start, off_t offset, int len,
+ int unused);
X
X static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
X int unused);
@@ -118,7 +121,7 @@
X 0, 9, "discovery",
X S_IFREG | S_IRUGO, 1, 0, 0,
X 0, NULL /* ops -- default to array */,
- &proc_discovery_read /* get_info */,
+ &discovery_proc_read /* get_info */,
X };
X
X struct proc_dir_entry proc_irda_device = {
@@ -184,7 +187,9 @@
X */
X void irda_proc_register(void) {
X proc_net_register(&proc_irda);
+#ifdef MODULE
X proc_irda.fill_inode = &irda_proc_modcount;
+#endif /* MODULE */
X proc_register(&proc_irda, &proc_lap);
X proc_register(&proc_irda, &proc_lmp);
X proc_register(&proc_irda, &proc_ttp);
@@ -311,73 +316,5 @@
X return 1;
X }
X
-/*
- * Function proc_discovery_read (buf, start, offset, len, unused)
- *
- * Print discovery information in /proc file system
- *
- */
-int proc_discovery_read(char *buf, char **start, off_t offset, int len,
- int unused)
-{
- DISCOVERY *discovery;
- struct lap_cb *lap;


- unsigned long flags;
-

- if ( !irlmp)
- return len;
X
- len = sprintf(buf, "IrLMP: Discovery log:\n\n");
-
- save_flags(flags);
- cli();
-
- lap = ( struct lap_cb *) hashbin_get_first( irlmp->links);
- while( lap != NULL) {
- ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;);
-
- len += sprintf( buf+len, "Link saddr=0x%08x\n", lap->saddr);
- discovery = ( DISCOVERY *) hashbin_get_first( lap->cachelog);
- while ( discovery != NULL) {
- len += sprintf( buf+len, " name: %s,",
- discovery->info);
-
- len += sprintf( buf+len, " hint: ");
- if ( discovery->hint[0] & HINT_PNP)
- len += sprintf( buf+len, "PnP Compatible ");
- if ( discovery->hint[0] & HINT_PDA)
- len += sprintf( buf+len, "PDA/Palmtop ");
- if ( discovery->hint[0] & HINT_COMPUTER)
- len += sprintf( buf+len, "Computer ");
- if ( discovery->hint[0] & HINT_PRINTER)
- len += sprintf( buf+len, "Printer ");
- if ( discovery->hint[0] & HINT_MODEM)
- len += sprintf( buf+len, "Modem ");
- if ( discovery->hint[0] & HINT_FAX)
- len += sprintf( buf+len, "Fax ");
- if ( discovery->hint[0] & HINT_LAN)
- len += sprintf( buf+len, "LAN Access");
-
- if ( discovery->hint[1] & HINT_TELEPHONY)
- len += sprintf( buf+len, "Telephony ");
- if ( discovery->hint[1] & HINT_FILE_SERVER)
- len += sprintf( buf+len, "File Server ");
- if ( discovery->hint[1] & HINT_COMM)
- len += sprintf( buf+len, "IrCOMM ");
- if ( discovery->hint[1] & HINT_OBEX)
- len += sprintf( buf+len, "IrOBEX ");
-
- len += sprintf( buf+len, ", daddr: 0x%08x\n",
- discovery->daddr);
-
- len += sprintf( buf+len, "\n");
-
- discovery = ( DISCOVERY *) hashbin_get_next( lap->cachelog);
- }
- lap = ( struct lap_cb *) hashbin_get_next( irlmp->links);
- }
- restore_flags(flags);
-
- return len;
-}
X
diff -u --recursive --new-file v2.2.5/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.2.5/linux/net/irda/irqueue.c Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irqueue.c Thu Apr 15 05:42:42 1999


@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Tue Jun 9 13:29:31 1998
- * Modified at: Mon Feb 8 09:05:51 1999
+ * Modified at: Thu Mar 11 13:27:04 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *

X * Copyright (C) 1998, Aage Kvalnes <aa...@cs.uit.no>
@@ -45,9 +45,10 @@
X * Create hashbin!
X *
X */
-hashbin_t *hashbin_new( int type)
+hashbin_t *hashbin_new(int type)
X {
X hashbin_t* hashbin;
+ int i;


X
X DEBUG( 4, __FUNCTION__ "()\n");
X

@@ -61,9 +62,13 @@
X /*
X * Initialize structure
X */
- memset( hashbin, 0, sizeof(hashbin_t));
+ memset(hashbin, 0, sizeof(hashbin_t));
X hashbin->hb_type = type;
X hashbin->magic = HB_MAGIC;
+
+ /* Make sure all spinlock's are unlocked */
+ for (i=0;i<HASHBIN_SIZE;i++)
+ hashbin->hb_mutex[i] = SPIN_LOCK_UNLOCKED;
X
X return hashbin;
X }
@@ -161,10 +166,9 @@
X bin = GET_HASHBIN( hashv);
X
X /* Synchronize */
- if ( hashbin->hb_type & HB_GLOBAL ) {
-
+ if ( hashbin->hb_type & HB_GLOBAL )
X spin_lock_irqsave( &hashbin->hb_mutex[ bin], flags);
- } else {
+ else {
X save_flags( flags);
X cli();
X }
@@ -176,27 +180,27 @@
X * Unlock the hashbin
X *
X */
-void hashbin_unlock( hashbin_t* hashbin, __u32 hashv, char* name,
- unsigned long flags)
+void hashbin_unlock(hashbin_t* hashbin, __u32 hashv, char* name,
+ unsigned long flags)
X {
X int bin;
X
- DEBUG( 0, "hashbin_unlock()\n");
+ DEBUG(0, "hashbin_unlock()\n");
X
- ASSERT( hashbin != NULL, return;);
- ASSERT( hashbin->magic == HB_MAGIC, return;);
+ ASSERT(hashbin != NULL, return;);
+ ASSERT(hashbin->magic == HB_MAGIC, return;);
X
X /*
X * Locate hashbin
X */
- if ( name )
- hashv = hash( name );
- bin = GET_HASHBIN( hashv );
+ if (name )
+ hashv = hash(name);
+ bin = GET_HASHBIN(hashv);
X
X /* Release lock */
- if ( hashbin->hb_type & HB_GLOBAL) {
+ if ( hashbin->hb_type & HB_GLOBAL)
X spin_unlock_irq( &hashbin->hb_mutex[ bin]);
- } else if ( hashbin->hb_type & HB_LOCAL) {
+ else if (hashbin->hb_type & HB_LOCAL) {
X restore_flags( flags);
X }
X }
diff -u --recursive --new-file v2.2.5/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.2.5/linux/net/irda/irttp.c Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irttp.c Thu Apr 15 05:42:42 1999


@@ -1,12 +1,12 @@
X /*********************************************************************
X *

X * Filename: irttp.c
- * Version: 1.0
+ * Version: 1.2
X * Description: Tiny Transport Protocol (TTP) implementation


X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Sat Feb 20 01:30:39 1999
+ * Modified at: Thu Mar 25 10:27:08 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,
@@ -30,6 +30,7 @@

X #include <asm/byteorder.h>
X
X #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
X #include <net/irda/irlmp.h>
X #include <net/irda/irttp.h>
X
@@ -37,15 +38,15 @@
X
X static void __irttp_close_tsap(struct tsap_cb *self);
X
-static void irttp_data_indication(void *instance, void *sap,
+static int irttp_data_indication(void *instance, void *sap,
+ struct sk_buff *skb);
+static int irttp_udata_indication(void *instance, void *sap,
X struct sk_buff *skb);
-static void irttp_udata_indication(void *instance, void *sap,
- struct sk_buff *skb);
X static void irttp_disconnect_indication(void *instance, void *sap,
X LM_REASON reason,
X struct sk_buff *);
X static void irttp_connect_indication(void *instance, void *sap,

- struct qos_info *qos, int max_sdu_size,

+ struct qos_info *qos, __u32 max_sdu_size,


X struct sk_buff *skb);
X

X static void irttp_run_tx_queue(struct tsap_cb *self);
@@ -127,8 +128,7 @@
X
X self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
X if (self == NULL) {
- printk(KERN_ERR "IrTTP: Can't allocate memory for "
- "TSAP control block!\n");
+ DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
X return NULL;
X }
X memset(self, 0, sizeof(struct tsap_cb));
@@ -136,7 +136,6 @@
X init_timer(&self->todo_timer);
X
X /* Initialize callbacks for IrLMP to use */
-
X irda_notify_init(&ttp_notify);
X ttp_notify.connect_confirm = irttp_connect_confirm;
X ttp_notify.connect_indication = irttp_connect_indication;
@@ -146,6 +145,12 @@
X ttp_notify.instance = self;
X strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
X
+ self->magic = TTP_TSAP_MAGIC;
+ self->connected = FALSE;
+
+ skb_queue_head_init(&self->rx_queue);
+ skb_queue_head_init(&self->tx_queue);
+ skb_queue_head_init(&self->rx_fragments);
X /*
X * Create LSAP at IrLMP layer
X */
@@ -165,24 +170,15 @@
X

X self->notify = *notify;

X self->lsap = lsap;
- self->magic = TTP_TSAP_MAGIC;
- self->connected = FALSE;
-
- skb_queue_head_init(&self->rx_queue);
- skb_queue_head_init(&self->tx_queue);
- skb_queue_head_init(&self->rx_fragments);
X
- /*
- * Insert ourself into the hashbin
- */
- hashbin_insert(irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
+ hashbin_insert(irttp->tsaps, (QUEUE *) self, (int) self, NULL);
X
X if (credit > TTP_MAX_QUEUE)
X self->initial_credit = TTP_MAX_QUEUE;
X else
X self->initial_credit = credit;
-
- return self;
+
+ return self;
X }
X
X /*
@@ -194,8 +190,6 @@
X */
X static void __irttp_close_tsap(struct tsap_cb *self)
X {


- DEBUG(4, __FUNCTION__ "()\n");

-
X /* First make sure we're connected. */
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -239,7 +233,7 @@
X return 0; /* Will be back! */
X }
X
- tsap = hashbin_remove(irttp->tsaps, self->stsap_sel, NULL);
+ tsap = hashbin_remove(irttp->tsaps, (int) self, NULL);
X
X ASSERT(tsap == self, return -1;);
X
@@ -295,8 +289,6 @@


X {
X __u8 *frame;
X

- DEBUG(4, __FUNCTION__ "()\n");

-
X ASSERT(self != NULL, return -1;);
X ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
X ASSERT(skb != NULL, return -1;);
@@ -304,7 +296,7 @@
X /* Check that nothing bad happens */
X if ((skb->len == 0) || (!self->connected)) {
X DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
- return -1;
+ return -ENOTCONN;
X }
X
X /*
@@ -314,7 +306,7 @@
X if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
X DEBUG(1, __FUNCTION__
X "(), SAR disabled, and data is to large for IrLAP!\n");
- return -1;
+ return -EMSGSIZE;
X }
X
X /*
@@ -322,11 +314,12 @@
X * TxMaxSduSize
X */
X if ((self->tx_max_sdu_size != 0) &&
+ (self->tx_max_sdu_size != SAR_UNBOUND) &&
X (skb->len > self->tx_max_sdu_size))
X {
X DEBUG(1, __FUNCTION__ "(), SAR enabled, "
X "but data is larger than TxMaxSduSize!\n");
- return -1;
+ return -EMSGSIZE;
X }
X /*
X * Check if transmit queue is full
@@ -337,7 +330,7 @@
X */
X irttp_run_tx_queue(self);
X
- return -1;
+ return -ENOBUFS;
X }
X
X /* Queue frame, or queue frame segments */
@@ -378,7 +371,7 @@
X }
X
X /*
- * Function irttp_xmit (self)
+ * Function irttp_run_tx_queue (self)
X *
X * If possible, transmit a frame queued for transmission.
X *
@@ -396,8 +389,7 @@
X if (irda_lock(&self->tx_queue_lock) == FALSE)
X return;
X
- while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)){
-
+ while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)) {
X skb = skb_dequeue(&self->tx_queue);
X ASSERT(skb != NULL, return;);
X
@@ -409,13 +401,12 @@
X * the code below is a critical region and we must assure that
X * nobody messes with the credits while we update them.
X */
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&self->lock, flags);
X
X n = self->avail_credit;
X self->avail_credit = 0;
X
- /* Only space for 127 credits in frame */
+ /* Only room for 127 credits in frame */
X if (n > 127) {
X self->avail_credit = n-127;
X n = 127;
@@ -423,10 +414,8 @@
X self->remote_credit += n;
X self->send_credit--;
X
- restore_flags(flags);
+ spin_unlock_irqrestore(&self->lock, flags);
X
- DEBUG(4, "irttp_xmit: Giving away %d credits\n", n);
-
X /*
X * More bit must be set by the data_request() or fragment()
X * functions
@@ -443,12 +432,14 @@
X
X /* Check if we can accept more frames from client */
X if ((self->tx_sdu_busy) &&
- (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) {
+ (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD))
+ {
X self->tx_sdu_busy = FALSE;
X
X if (self->notify.flow_indication)
X self->notify.flow_indication(
- self->notify.instance, self, FLOW_START);
+ self->notify.instance, self,
+ FLOW_START);
X }
X }
X
@@ -487,8 +478,7 @@
X * the code below is a critical region and we must assure that
X * nobody messes with the credits while we update them.
X */
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&self->lock, flags);
X
X n = self->avail_credit;
X self->avail_credit = 0;
@@ -500,7 +490,7 @@
X }
X self->remote_credit += n;
X
- restore_flags(flags);
+ spin_unlock_irqrestore(&self->lock, flags);
X
X skb_put(tx_skb, 1);
X tx_skb->data[0] = (__u8) (n & 0x7f);
@@ -512,10 +502,11 @@
X /*
X * Function irttp_udata_indication (instance, sap, skb)
X *
- *
+ * Received some unit-data (unreliable)
X *
X */
-void irttp_udata_indication(void *instance, void *sap, struct sk_buff *skb)
+static int irttp_udata_indication(void *instance, void *sap,

+ struct sk_buff *skb)
X {

X struct tsap_cb *self;
X
@@ -523,15 +514,17 @@
X
X self = (struct tsap_cb *) instance;


X
- ASSERT(self != NULL, return;);

- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);


- ASSERT(skb != NULL, return;);

+ ASSERT(self != NULL, return -1;);

+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);


+ ASSERT(skb != NULL, return -1;);
X

X /* Just pass data to layer above */
X if (self->notify.udata_indication) {
X self->notify.udata_indication(self->notify.instance, self, skb);
X }
X self->stats.rx_packets++;


+
+ return 0;
X }
X

X /*
@@ -540,7 +533,8 @@
X * Receive segment from IrLMP.
X *
X */
-void irttp_data_indication(void *instance, void *sap, struct sk_buff *skb)
+static int irttp_data_indication(void *instance, void *sap,

+ struct sk_buff *skb)
X {

X struct tsap_cb *self;
X int more;
@@ -549,17 +543,17 @@
X
X self = (struct tsap_cb *) instance;


X
- ASSERT(self != NULL, return;);

- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);


- ASSERT(skb != NULL, return;);

+ ASSERT(self != NULL, return -1;);

+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);


+ ASSERT(skb != NULL, return -1;);
X

X frame = skb->data;
X

X n = frame[0] & 0x7f; /* Extract the credits */
X more = frame[0] & 0x80;
X
- DEBUG(4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n",
- n, self->stsap_sel);
+ DEBUG(3, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n",
+ n, self->stsap_sel);
X
X self->stats.rx_packets++;
X
@@ -600,6 +594,7 @@
X */
X if (self->send_credit == n)
X irttp_start_todo_timer(self, 0);


+ return 0;
X }
X
X /*

@@ -638,25 +633,26 @@
X * Try to connect to remote destination TSAP selector
X *
X */
-void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
- __u32 saddr, __u32 daddr,


- struct qos_info *qos, int max_sdu_size,

- struct sk_buff *userdata)
+int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
+ __u32 saddr, __u32 daddr,


+ struct qos_info *qos, __u32 max_sdu_size,

+ struct sk_buff *userdata)

X {
X struct sk_buff *skb;

+ __u16 tmp_be;
X __u8 *frame;
X __u8 n;
X
X DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size);

X
- ASSERT(self != NULL, return;);

- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);


+ ASSERT(self != NULL, return -1;);

+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
X
X /* Any userdata supplied? */
X if (userdata == NULL) {
X skb = dev_alloc_skb(64);
X if (!skb)
- return;
+ return -ENOMEM;
X
X /* Reserve space for MUX_CONTROL and LAP header */
X skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
@@ -667,7 +663,7 @@
X * headers
X */
X ASSERT(skb_headroom(userdata) >=
- (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
+ (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return -1;);
X }
X
X /* Initialize connection parameters */
@@ -697,7 +693,7 @@
X if (max_sdu_size > 0) {
X ASSERT(skb_headroom(skb) >=
X (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER),
- return;);
+ return -1;);
X
X /* Insert SAR parameters */
X frame = skb_push(skb, TTP_HEADER_WITH_SAR);
@@ -706,7 +702,9 @@
X frame[1] = 0x04; /* Length */
X frame[2] = 0x01; /* MaxSduSize */
X frame[3] = 0x02; /* Value length */
- *((__u16 *) (frame+4))= htons(max_sdu_size); /* Big endian! */
+
+ tmp_be = cpu_to_be16((__u16) max_sdu_size);
+ memcpy(frame+4, &tmp_be, 2);
X } else {
X /* Insert plain TTP header */
X frame = skb_push(skb, TTP_HEADER);
@@ -716,7 +714,8 @@
X }
X
X /* Connect with IrLMP. No QoS parameters for now */
- irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos, skb);
+ return irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos,
+ skb);
X }
X
X /*
@@ -726,12 +725,14 @@
X *
X */
X void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
- int max_seg_size, struct sk_buff *skb)
+ __u32 max_seg_size, struct sk_buff *skb)
X {
X struct tsap_cb *self;
+ __u16 tmp_cpu;
X __u8 *frame;
X __u8 n;
X int parameters;
+ __u8 plen, pi, pl;


X
X DEBUG(4, __FUNCTION__ "()\n");
X

@@ -765,9 +766,16 @@
X
X parameters = frame[0] & 0x80;
X if (parameters) {
- DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
-
- self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
+ plen = frame[1];
+ pi = frame[2];
+ pl = frame[3];
+
+ ASSERT(pl == 2, return;);
+
+ memcpy(&tmp_cpu, frame+4, 2); /* Align value */
+ be16_to_cpus(&tmp_cpu); /* Convert to host order */
+ self->tx_max_sdu_size = tmp_cpu;
+
X DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n",
X self->tx_max_sdu_size);
X }
@@ -791,14 +799,16 @@
X *
X */
X void irttp_connect_indication(void *instance, void *sap,
- struct qos_info *qos, int max_seg_size,
+ struct qos_info *qos, __u32 max_seg_size,

X struct sk_buff *skb)
X {

X struct tsap_cb *self;
X struct lsap_cb *lsap;
+ __u16 tmp_cpu;
X __u8 *frame;
X int parameters;
X int n;
+ __u8 plen, pi, pl;
X
X self = (struct tsap_cb *) instance;
X
@@ -827,15 +837,23 @@
X parameters = frame[0] & 0x80;
X if (parameters) {
X DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
-
- self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
+ plen = frame[1];
+ pi = frame[2];
+ pl = frame[3];
+
+ ASSERT(pl == 2, return;);
+
+ memcpy(&tmp_cpu, frame+4, 2); /* Align value */
+ be16_to_cpus(&tmp_cpu); /* Convert to host order */
+
+ self->tx_max_sdu_size = tmp_cpu;
X DEBUG(4, __FUNCTION__ "(), MaxSduSize=%d\n",
X self->tx_max_sdu_size);
X }
X
X DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
X
- skb_pull(skb, 1);
+ skb_pull(skb, 1); /* Remove TTP header */
X
X if (self->notify.connect_indication) {
X self->notify.connect_indication(self->notify.instance, self,
@@ -851,10 +869,11 @@
X * IrLMP!
X *
X */
-void irttp_connect_response(struct tsap_cb *self, int max_sdu_size,
+void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
X struct sk_buff *userdata)


X {
X struct sk_buff *skb;

+ __u32 tmp_be;
X __u8 *frame;
X __u8 n;
X
@@ -912,7 +931,9 @@
X frame[1] = 0x04; /* Length */
X frame[2] = 0x01; /* MaxSduSize */
X frame[3] = 0x02; /* Value length */
- *((__u16 *) (frame+4))= htons(max_sdu_size);
+
+ tmp_be = cpu_to_be16((__u16)max_sdu_size);
+ memcpy(frame+4, &tmp_be, 2);
X } else {
X /* Insert TTP header */
X frame = skb_push(skb, TTP_HEADER);
@@ -924,6 +945,44 @@
X }
X
X /*
+ * Function irttp_dup (self, instance)
+ *
+ * Duplicate TSAP, can be used by servers to confirm a connection on a
+ * new TSAP so it can keep listening on the old one.
+ */
+struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+{
+ struct tsap_cb *new;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
+ DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
+ return NULL;
+ }
+ new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ if (!new) {
+ DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+ return NULL;
+ }
+ /* Dup */
+ memcpy(new, orig, sizeof(struct tsap_cb));
+ new->notify.instance = instance;
+ new->lsap = irlmp_dup(orig->lsap, new);
+
+ /* Not everything should be copied */
+ init_timer(&new->todo_timer);
+
+ skb_queue_head_init(&new->rx_queue);
+ skb_queue_head_init(&new->tx_queue);
+ skb_queue_head_init(&new->rx_fragments);
+
+ hashbin_insert(irttp->tsaps, (QUEUE *) new, (int) new, NULL);
+
+ return new;
+}
+
+/*
X * Function irttp_disconnect_request (self)
X *
X * Close this connection please! If priority is high, the queued data
@@ -1028,12 +1087,44 @@
X

X self->connected = FALSE;
X

- /*
- * Use callback to notify layer above
+ if (!self->notify.disconnect_indication)
+ return;
+
+ self->notify.disconnect_indication(self->notify.instance, self, reason,
+ userdata);
+}
+
+/*
+ * Function irttp_do_data_indication (self, skb)
+ *
+ * Try to deliver reassebled skb to layer above, and requeue it if that
+ * for some reason should fail. We mark rx sdu as busy to apply back
+ * pressure is necessary.
+ */
+void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb)
+{
+ int err;
+
+ err = self->notify.data_indication(self->notify.instance, self, skb);
+
+ /* Usually the layer above will notify that it's input queue is
+ * starting to get filled by using the flow request, but this may
+ * be difficult, so it can instead just refuse to eat it and just
+ * give an error back
X */
- if (self->notify.disconnect_indication)
- self->notify.disconnect_indication(self->notify.instance,
- self, reason, userdata);
+ if (err == -ENOMEM) {
+ DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
+
+ /* Make sure we take a break */
+ self->rx_sdu_busy = TRUE;
+
+ /* Need to push the header in again */
+ skb_push(skb, TTP_HEADER);
+ skb->data[0] = 0x00; /* Make sure MORE bit is cleared */
+
+ /* Put skb back on queue */
+ skb_queue_head(&self->rx_queue, skb);
+ }
X }
X
X /*
@@ -1045,15 +1136,7 @@
X void irttp_run_rx_queue(struct tsap_cb *self)

X {
X struct sk_buff *skb;
- __u8 *frame;

X int more = 0;
- void *instance;
-


- ASSERT(self != NULL, return;);

- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
-
- instance = self->notify.instance;
- ASSERT(instance != NULL, return;);
X
X DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
X self->send_credit, self->avail_credit, self->remote_credit);
@@ -1062,20 +1145,12 @@
X return;
X
X /*
- * Process receive queue
+ * Reassemble all frames in receive queue and deliver them
X */
- while ((!skb_queue_empty(&self->rx_queue)) && !self->rx_sdu_busy) {
-
- skb = skb_dequeue(&self->rx_queue);
- if (!skb)
- break; /* Should not happend, but ... */
-
+ while (!self->rx_sdu_busy && (skb = skb_dequeue(&self->rx_queue))) {
X self->avail_credit++;
X

- frame = skb->data;

- more = frame[0] & 0x80;
- DEBUG(4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" :
- "FALSE");
+ more = skb->data[0] & 0x80;
X
X /* Remove TTP header */
X skb_pull(skb, TTP_HEADER);
@@ -1089,10 +1164,10 @@
X * immediately. This can be requested by clients that
X * implements byte streams without any message boundaries
X */
- if ((self->no_defrag) || (self->rx_max_sdu_size == 0)) {
- self->notify.data_indication(instance, self, skb);
+ if (self->rx_max_sdu_size == SAR_DISABLE) {
+ irttp_do_data_indication(self, skb);
X self->rx_sdu_size = 0;
-
+
X continue;
X }
X
@@ -1103,43 +1178,47 @@
X * limits of the maximum size of the rx_sdu
X */
X if (self->rx_sdu_size <= self->rx_max_sdu_size) {
- DEBUG(4, __FUNCTION__
- "(), queueing fragment\n");
-
+ DEBUG(4, __FUNCTION__ "(), queueing frag\n");


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'
fi

echo 'End of part 33'
echo 'File patch-2.2.6 is continued in part 34'
echo 34 > _shar_seq_.tmp
exit 0

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

unread,
Apr 20, 1999, 3:00:00 AM4/20/99
to
Archive-name: v2.2/patch-2.2.6/part34

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


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

if test "$Scheck" != 34; 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.6'
else
echo 'x - continuing with patch-2.2.6'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.6' &&

X skb_queue_tail(&self->rx_fragments, skb);
X } else {
- DEBUG(1, __FUNCTION__ "(), Error!\n");
+ /* Free the part of the SDU that is too big */
+ dev_kfree_skb(skb);
X }
- } else {
- /*
- * This is the last fragment, so time to reassemble!
+ continue;
+ }
+ /*
+ * This is the last fragment, so time to reassemble!
+ */
+ if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
+ (self->rx_max_sdu_size == SAR_UNBOUND))
+ {
+ /*
+ * A little optimizing. Only queue the fragment if
+ * there are other fragments. Since if this is the
+ * last and only fragment, there is no need to
+ * reassemble :-)
X */
- if (self->rx_sdu_size <= self->rx_max_sdu_size) {
-
- /* A little optimizing. Only queue the
- * fragment if there is other fragments. Since
- * if this is the last and only fragment,
- * there is no need to reassemble
- */
- if (!skb_queue_empty(&self->rx_fragments)) {
-


- DEBUG(4, __FUNCTION__
- "(), queueing fragment\n");

- skb_queue_tail(&self->rx_fragments,
- skb);
-
- skb = irttp_reassemble_skb(self);
- }
- self->notify.data_indication(instance, self,
- skb);


- } else {
- DEBUG(1, __FUNCTION__

- "(), Truncated frame\n");
- self->notify.data_indication(
- self->notify.instance, self, skb);
+ if (!skb_queue_empty(&self->rx_fragments)) {
+ skb_queue_tail(&self->rx_fragments,
+ skb);
+
+ skb = irttp_reassemble_skb(self);
X }
- self->rx_sdu_size = 0;
+
+ /* Now we can deliver the reassembled skb */
+ irttp_do_data_indication(self, skb);
+ } else {
+ DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
+
+ /* Free the part of the SDU that is too big */
+ dev_kfree_skb(skb);
+
+ /* Deliver only the valid but truncated part of SDU */
+ skb = irttp_reassemble_skb(self);
+
+ irttp_do_data_indication(self, skb);
X }
+ self->rx_sdu_size = 0;
X }
X /* Reset lock */
X self->rx_queue_lock = 0;
@@ -1194,6 +1273,11 @@
X if (!skb)
X return NULL;
X
+ /*
+ * Need to reserve space for TTP header in case this skb needs to
+ * be requeued in case delivery failes
+ */
+ skb_reserve(skb, TTP_HEADER);
X skb_put(skb, self->rx_sdu_size);
X
X /*
@@ -1310,6 +1394,9 @@
X if (self->disconnect_pend) {
X /* Check if it's possible to disconnect yet */
X if (skb_queue_empty(&self->tx_queue)) {
+
+ /* Make sure disconnect is not pending anymore */
+ self->disconnect_pend = FALSE;
X if (self->disconnect_skb) {
X irttp_disconnect_request(
X self, self->disconnect_skb, P_NORMAL);
diff -u --recursive --new-file v2.2.5/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.2.5/linux/net/irda/wrapper.c Wed Mar 10 15:29:53 1999
+++ linux/net/irda/wrapper.c Thu Apr 15 05:42:42 1999


@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>

X * Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Tue Feb 16 17:27:23 1999
+ * Modified at: Fri Mar 26 21:52:53 1999


X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,

@@ -60,10 +60,9 @@
X fcs.value = INIT_FCS;
X n = 0;
X
- if ( skb->len > 2048) {
- DEBUG( 0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n",
- (int) skb->len);
-
+ if (skb->len > 2048) {
+ DEBUG(0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n",
+ (int) skb->len);


X return 0;
X }
X

@@ -71,8 +70,13 @@
X * Send XBOF's for required min. turn time and for the negotiated
X * additional XBOFS
X */
- xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
- for ( i=0; i<xbofs; i++) {
+ if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
+ DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
+ xbofs = 11;
+ } else
+ xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
+
+ for (i=0; i<xbofs; i++) {
X tx_buff[n++] = XBOF;
X }
X
@@ -80,7 +84,7 @@
X tx_buff[n++] = BOF;
X
X /* Insert frame and calc CRC */
- for( i=0; i < skb->len; i++) {
+ for (i=0; i < skb->len; i++) {
X byte = skb->data[i];
X
X /*
@@ -100,11 +104,11 @@
X /* Insert CRC in little endian format (LSB first) */
X fcs.value = ~fcs.value;
X #ifdef __LITTLE_ENDIAN
- n += stuff_byte( fcs.bytes[0], tx_buff+n);
- n += stuff_byte( fcs.bytes[1], tx_buff+n);
+ n += stuff_byte(fcs.bytes[0], tx_buff+n);
+ n += stuff_byte(fcs.bytes[1], tx_buff+n);
X #else ifdef __BIG_ENDIAN
- n += stuff_byte( fcs.bytes[1], tx_buff+n);
- n += stuff_byte( fcs.bytes[0], tx_buff+n);
+ n += stuff_byte(fcs.bytes[1], tx_buff+n);
+ n += stuff_byte(fcs.bytes[0], tx_buff+n);
X #endif
X tx_buff[n++] = EOF;
X
@@ -127,7 +131,7 @@
X return;
X }
X
- /* Align to 20 bytes */
+ /* Align IP header to 20 bytes */
X skb_reserve( skb, 1);
X
X ASSERT( len-2 > 0, return;);
diff -u --recursive --new-file v2.2.5/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.2.5/linux/net/netlink/af_netlink.c Mon Mar 29 11:09:12 1999
+++ linux/net/netlink/af_netlink.c Thu Apr 15 05:42:43 1999
@@ -25,7 +25,6 @@
X #include <linux/un.h>
X #include <linux/fcntl.h>
X #include <linux/termios.h>
-#include <linux/socket.h>
X #include <linux/sockios.h>
X #include <linux/net.h>
X #include <linux/fs.h>
diff -u --recursive --new-file v2.2.5/linux/scripts/ver_linux linux/scripts/ver_linux
--- v2.2.5/linux/scripts/ver_linux Tue Mar 23 14:35:48 1999
+++ linux/scripts/ver_linux Fri Apr 16 08:20:23 1999
@@ -20,10 +20,7 @@
X '{print "Linux C++ Library " $4"."$5"."$6}'
X ps --version 2>&1 | awk 'NR==1{print "Procps ", $NF}'
X mount --version | awk -F\- '{print "Mount ", $NF}'
-netstat --version | awk \
-'NR==1{if ($5 != "") { n=split($5,buf,"-"); ver=buf[n]; done=1 }}
- NR==2{if (done != 1) ver=$3 }
- END{print "Net-tools ",ver}'
+hostname -V 2>&1 | awk 'NR==1{print "Net-tools ", $NF}'
X loadkeys -h 2>&1 | awk \
X '(NR==1 && $3) {ver=$3}
X (NR==2 && $1 ~ /console-tools/) {print "Console-tools ",$3; done=1}


SHAR_EOF
true || echo 'restore of patch-2.2.6 failed'

echo 'File patch-2.2.6 is complete' &&
chmod 644 patch-2.2.6 ||


echo 'restore of patch-2.2.6 failed'

Cksum="`cksum < 'patch-2.2.6'`"
if ! test "3561897829 1908816" = "$Cksum"
then
echo 'patch-2.2.6: original Checksum 3561897829 1908816, current one' "$Cksum"
rm -f _shar_wnt_.tmp
rm -f _shar_seq_.tmp
exit 1
fi
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo 'You have unpacked the last part.'

0 new messages