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

7 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;
+ defau