lines    added  deleted
linux/CREDITS                                       :      45       16        2
linux/Documentation/Configure.help                  :     263      122       46
linux/Documentation/isdn/CREDITS                    :       8        1        1
linux/Documentation/kernel-parameters.txt           :     336      336        0
linux/Documentation/networking/ethertap.txt         :      23        4        4
linux/Documentation/networking/ltpc.txt             :       8        1        1
linux/Documentation/scsi-generic.txt                :     807      295      200
linux/Documentation/sound/CMI8330                   :     104       33       21
linux/Documentation/svga.txt                        :      24        8        2
linux/Documentation/video4linux/API.html            :      60       24        4
linux/Documentation/video4linux/bttv/CONTRIBUTORS   :       8        1        1
linux/Documentation/video4linux/bttv/PROBLEMS       :      31        7        7
linux/Documentation/video4linux/bttv/README.RADIO   :       8        1        1
linux/Documentation/video4linux/bttv/README.WINVIEW :      33       33        0
linux/Documentation/video4linux/bttv/THANKS         :       8        1        1
linux/MAINTAINERS                                   :      11        5        0
linux/Makefile                                      :       7        1        1
linux/README                                        :      22        3        3
linux/arch/alpha/config.in                          :      20        6        1
linux/arch/alpha/defconfig                          :     203       57       25
linux/arch/alpha/kernel/alpha_ksyms.c               :      18        3        2
linux/arch/alpha/kernel/core_cia.c                  :      19        5        1
linux/arch/alpha/kernel/fpreg.c                     :      21        3        3
linux/arch/alpha/kernel/head.S                      :     125       19       98
linux/arch/alpha/kernel/irq.c                       :      22        9        1
linux/arch/alpha/kernel/process.c                   :      62       29       16
linux/arch/alpha/kernel/proto.h                     :      17        3        1
linux/arch/alpha/kernel/setup.c                     :      40        8        2
linux/arch/alpha/kernel/signal.c                    :       9        3        0
linux/arch/alpha/kernel/smp.c                       :    1635      689      650
linux/arch/alpha/kernel/sys_dp264.c                 :     355      176       77
linux/arch/alpha/kernel/sys_takara.c                :     139       70       20
linux/arch/alpha/kernel/time.c                      :     173       64       28
linux/arch/alpha/kernel/traps.c                     :      93        6       15
linux/arch/alpha/mm/init.c                          :      26        0       20
linux/arch/i386/boot/setup.S                        :      33       14        4
linux/arch/i386/boot/video.S                        :      31        9        4
linux/arch/i386/kernel/mca.c                        :     106       29       18
linux/arch/i386/kernel/mtrr.c                       :     340      115       26
linux/arch/i386/kernel/setup.c                      :      55       20        7
linux/arch/i386/kernel/signal.c                     :       7        1        0
linux/arch/i386/kernel/smp.c                        :       8        1        1
linux/arch/i386/lib/checksum.S                      :       8        1        1
linux/arch/ppc/Makefile                             :      10        4        0
linux/arch/ppc/boot/Makefile                        :      17        8        2
linux/arch/ppc/boot/misc.c                          :      17        2        2
linux/arch/ppc/chrpboot/Makefile                    :      53       13        7
linux/arch/ppc/chrpboot/main.c                      :      72       12       18
linux/arch/ppc/coffboot/Makefile                    :      18        8        2
linux/arch/ppc/coffboot/zlib.c                      :      20        6        1
linux/arch/ppc/common_defconfig                     :     193       51       29
linux/arch/ppc/config.in                            :      28        8        3
linux/arch/ppc/defconfig                            :     232       24       73
linux/arch/ppc/kernel/Makefile                      :       8        1        1
linux/arch/ppc/kernel/chrp_pci.c                    :     106       74        5
linux/arch/ppc/kernel/chrp_setup.c                  :     180       60       47
linux/arch/ppc/kernel/head.S                        :     231       89       14
linux/arch/ppc/kernel/idle.c                        :      14        2        1
linux/arch/ppc/kernel/irq.c                         :      14        1        2
linux/arch/ppc/kernel/misc.S                        :      27        4        9
linux/arch/ppc/kernel/prep_pci.c                    :      24        5        1
linux/arch/ppc/kernel/prep_setup.c                  :      21        3        5
linux/arch/ppc/kernel/prom.c                        :      94       23        7
linux/arch/ppc/kernel/ptrace.c                      :      13        5        1
linux/arch/ppc/kernel/residual.c                    :       6        1        1
linux/arch/ppc/kernel/setup.c                       :      14        1        2
linux/arch/ppc/kernel/smp.c                         :      19        4        1
linux/arch/ppc/kernel/softemu8xx.c                  :      20        7        0
linux/arch/ppc/kernel/syscalls.c                    :      40        6       13
linux/arch/ppc/kernel/time.c                        :      25        6        2
linux/arch/ppc/kernel/traps.c                       :      23        0        3
linux/arch/ppc/mm/fault.c                           :      15        0        2
linux/arch/ppc/mm/init.c                            :      33        4        4
linux/arch/sparc/defconfig                          :       7        1        0
linux/arch/sparc/kernel/signal.c                    :      13        2        1
linux/arch/sparc/kernel/sys_sunos.c                 :      14        2        2
linux/arch/sparc64/defconfig                        :       7        1        0
linux/arch/sparc64/kernel/ioctl32.c                 :      48       23        1
linux/arch/sparc64/kernel/setup.c                   :      15        3        1
linux/arch/sparc64/kernel/signal.c                  :      13        2        1
linux/arch/sparc64/kernel/signal32.c                :      13        2        1
linux/arch/sparc64/kernel/sys_sparc32.c             :     128      100        4
linux/arch/sparc64/kernel/sys_sunos32.c             :      14        2        2
linux/arch/sparc64/solaris/fs.c                     :      73       12       16
linux/drivers/block/floppy.c                        :      17        1        3
linux/drivers/block/ide.c                           :      48       17        4
linux/drivers/block/loop.c                          :       8        2        0
linux/drivers/block/ns87415.c                       :      25       17        0
linux/drivers/char/acquirewdt.c                     :      19        3        3
linux/drivers/char/bttv.c                           :     106       65        0
linux/drivers/char/bttv.h                           :      55       28        1
linux/drivers/char/cyclades.c                       :     762      208      149
linux/drivers/char/n_hdlc.c                         :      69       26       15
linux/drivers/char/pc110pad.c                       :      14        3        3
linux/drivers/char/pms.c                            :       8        1        1
linux/drivers/char/radio-cadet.c                    :      35        7        8
linux/drivers/char/softdog.c                        :      10        2        2
linux/drivers/char/synclink.c                       :     906      420      102
linux/drivers/char/tuner.c                          :      10        3        1
linux/drivers/char/tuner.h                          :       7        1        0
linux/drivers/char/videodev.c                       :       8        1        1
linux/drivers/char/wdt.c                            :      28        5        3
linux/drivers/misc/parport_pc.c                     :      27        6        3
linux/drivers/misc/parport_share.c                  :      12        3        3
linux/drivers/net/3c515.c                           :      23        3        0
linux/drivers/net/Config.in                         :       7        1        0
linux/drivers/net/Makefile                          :      14        8        0
linux/drivers/net/Space.c                           :      17        4        0
linux/drivers/net/cosa.c                            :      63       17        1
linux/drivers/net/cs89x0.c                          :       8        1        1
linux/drivers/net/eexpress.c                        :      59       20        4
linux/drivers/net/ibmtr.c                           :      18        4        1
linux/drivers/net/irda/Config.in                    :      38       20       13
linux/drivers/net/irda/Makefile                     :     100       80        0
linux/drivers/net/irda/actisys.c                    :     272       55       95
linux/drivers/net/irda/esi.c                        :     167       28       50
linux/drivers/net/irda/girbil.c                     :     223       28       67
linux/drivers/net/irda/irport.c                     :     762      448      107
linux/drivers/net/irda/irtty.c                      :     278       43      125
linux/drivers/net/irda/litelink.c                   :     206      206        0
linux/drivers/net/irda/pc87108.c                    :     515      131      123
linux/drivers/net/irda/smc-ircc.c                   :     969      969        0
linux/drivers/net/irda/tekram.c                     :     224       33       73
linux/drivers/net/irda/toshoboe.c                   :     901      901        0
linux/drivers/net/irda/uircc.c                      :      75       11        7
linux/drivers/net/irda/w83977af_ir.c                :    1126      291      242
linux/drivers/net/ni52.c                            :       8        1        1
linux/drivers/net/ni52.h                            :       8        1        1
linux/drivers/net/ni65.c                            :      36        6        2
linux/drivers/net/shaper.c                          :      10        2        2
linux/drivers/net/sk_mca.c                          :    1143     1143        0
linux/drivers/net/sk_mca.h                          :     175      174        0
linux/drivers/net/smc-ultra.c                       :      10        1        1
linux/drivers/net/sunhme.c                          :       8        1        1
linux/drivers/pci/oldproc.c                         :      81       23        1
linux/drivers/sbus/char/Config.in                   :       5        1        0
linux/drivers/sbus/char/Makefile                    :      14        8        0
linux/drivers/sbus/char/aurora.c                    :    2370     2370        0
linux/drivers/sbus/char/aurora.h                    :     278      278        0
linux/drivers/sbus/char/cd180.h                     :     240      240        0
linux/drivers/sbus/sbus.c                           :      25        7        1
linux/drivers/scsi/Config.in                        :      12        2        4
linux/drivers/scsi/README.aic7xxx                   :      63       17       12
linux/drivers/scsi/README.st                        :      24        1       10
linux/drivers/scsi/aic7xxx/aic7xxx.reg              :     145       78        0
linux/drivers/scsi/aic7xxx/aic7xxx.seq              :     509      137      112
linux/drivers/scsi/aic7xxx/scsi_message.h           :      13        9        1
linux/drivers/scsi/aic7xxx.c                        :    3280     1316      669
linux/drivers/scsi/aic7xxx_proc.c                   :     105       32       23
linux/drivers/scsi/aic7xxx_reg.h                    :      91       42        0
linux/drivers/scsi/aic7xxx_seq.c                    :     986      344      315
linux/drivers/scsi/scsi.c                           :      39       12        0
linux/drivers/scsi/scsi.h                           :       7        1        0
linux/drivers/scsi/scsi_proc.c                      :       8        1        1
linux/drivers/scsi/scsi_syms.c                      :      22        2        3
linux/drivers/scsi/scsicam.c                        :      37        4        5
linux/drivers/scsi/sd.c                             :      28        4        4
linux/drivers/scsi/sg.c                             :    1160      407      270
linux/drivers/scsi/sr_ioctl.c                       :      12        1        3
linux/drivers/scsi/st.c                             :      33        2        4
linux/drivers/scsi/st.h                             :       7        0        1
linux/drivers/scsi/sym53c8xx.c                      :       8        2        0
linux/drivers/sound/es1370.c                        :     157       39       14
linux/drivers/sound/sound_core.c                    :      31       17        1
linux/drivers/video/cgsixfb.c                       :      55       20        5
linux/drivers/video/fbcon.c                         :       4        1        0
linux/drivers/video/mdacon.c                        :       8        1        1
linux/fs/Config.in                                  :      22        3        6
linux/fs/adfs/dir.c                                 :       9        0        3
linux/fs/adfs/namei.c                               :      19        0        6
linux/fs/autofs/dir.c                               :       8        0        2
linux/fs/autofs/root.c                              :       9        0        3
linux/fs/binfmt_elf.c                               :       8        2        0
linux/fs/block_dev.c                                :       8        2        0
linux/fs/coda/inode.c                               :       8        1        1
linux/fs/coda/psdev.c                               :       8        1        1
linux/fs/exec.c                                     :      12        5        1
linux/fs/ext2/file.c                                :      77       39       10
linux/fs/ext2/namei.c                               :       9        2        1
linux/fs/ext2/truncate.c                            :       9        2        1
linux/fs/hfs/dir_cap.c                              :      10        0        4
linux/fs/hfs/dir_dbl.c                              :      10        0        4
linux/fs/hfs/dir_nat.c                              :      10        0        4
linux/fs/minix/namei.c                              :     133       11       52
linux/fs/ncpfs/dir.c                                :      44        3       16
linux/fs/ncpfs/file.c                               :     142       42       17
linux/fs/ncpfs/inode.c                              :      22        3        2
linux/fs/ncpfs/ioctl.c                              :      69       25       15
linux/fs/ncpfs/mmap.c                               :      72       12       27
linux/fs/ncpfs/ncplib_kernel.c                      :     127       49       38
linux/fs/ncpfs/ncplib_kernel.h                      :      30       10        6
linux/fs/ncpfs/sock.c                               :     106       18       14
linux/fs/nfs/read.c                                 :       7        1        0
linux/fs/select.c                                   :      13        5        1
linux/fs/smbfs/inode.c                              :      99       18       33
linux/fs/smbfs/proc.c                               :     383       75       53
linux/fs/super.c                                    :      29       13       10
linux/fs/sysv/namei.c                               :     153       13       60
linux/include/asm-alpha/atomic.h                    :      15        2        0
linux/include/asm-alpha/bitops.h                    :      47       11        2
linux/include/asm-alpha/init.h                      :      17        3        1
linux/include/asm-alpha/io.h                        :      19        4        3
linux/include/asm-alpha/irq.h                       :      11        4        0
linux/include/asm-alpha/mmu_context.h               :       9        2        1
linux/include/asm-alpha/smp.h                       :      41       11        4
linux/include/asm-alpha/spinlock.h                  :      50       14        8
linux/include/asm-alpha/system.h                    :     190       81       69
linux/include/asm-arm/arch-ebsa285/irq.h            :       7        1        0
linux/include/asm-arm/arch-ebsa285/memory.h         :       8        2        0
linux/include/asm-i386/bugs.h                       :      21       11        3
linux/include/asm-i386/locks.h                      :       8        1        1
linux/include/asm-ppc/system.h                      :      26        5        1
linux/include/asm-sparc/spinlock.h                  :       8        1        1
linux/include/asm-sparc64/spinlock.h                :       8        1        1
linux/include/linux/cyclades.h                      :       9        2        1
linux/include/linux/if_ether.h                      :       8        1        1
linux/include/linux/if_fddi.h                       :       8        1        1
linux/include/linux/if_hippi.h                      :       8        1        1
linux/include/linux/interrupt.h                     :       7        1        0
linux/include/linux/lp.h                            :      35       10        6
linux/include/linux/major.h                         :       8        2        0
linux/include/linux/ncp.h                           :       9        0        3
linux/include/linux/ncp_fs.h                        :      12        5        1
linux/include/linux/ncp_fs_sb.h                     :      16        2        1
linux/include/linux/netdevice.h                     :       8        1        1
linux/include/linux/pci.h                           :      71       22        1
linux/include/linux/smb.h                           :       8        1        1
linux/include/linux/smb_fs.h                        :      22       16        0
linux/include/linux/smp.h                           :       8        1        1
linux/include/linux/synclink.h                      :      56       13        3
linux/include/net/irda/crc.h                        :      34        9        6
linux/include/net/irda/dongle.h                     :      40        8        6
linux/include/net/irda/ircomm_common.h              :      60        8       11
linux/include/net/irda/irda.h                       :      34        6        4
linux/include/net/irda/irda_device.h                :     125       48       14
linux/include/net/irda/iriap.h                      :      30        4        4
linux/include/net/irda/irlan_common.h               :     120       30       16
linux/include/net/irda/irlan_eth.h                  :      20        3        2
linux/include/net/irda/irlan_provider.h             :      26        2        8
linux/include/net/irda/irlap.h                      :      56       11        7
linux/include/net/irda/irlmp.h                      :      21        3        3
linux/include/net/irda/irlpt_common.h               :       9        2        1
linux/include/net/irda/irport.h                     :      32        8        7
linux/include/net/irda/irqueue.h                    :      17        1        3
linux/include/net/irda/irttp.h                      :      50        7        7
linux/include/net/irda/irtty.h                      :      57        9       18
linux/include/net/irda/irvtd.h                      :      18        4        1
linux/include/net/irda/smc-ircc.h                   :     160      160        0
linux/include/net/irda/smc_ircc.h                   :     123        0      123
linux/include/net/irda/toshoboe.h                   :     165      165        0
linux/include/net/irda/w83977af_ir.h                :      42       25        2
linux/include/net/irda/wrapper.h                    :      43       10        8
linux/include/net/tcp.h                             :       8        1        1
linux/include/scsi/scsicam.h                        :       6        2        0
linux/include/scsi/sg.h                             :     272       87       90
linux/kernel/signal.c                               :      24        3        1
linux/kernel/sys.c                                  :       8        2        0
linux/mm/memory.c                                   :      58       14        8
linux/mm/swapfile.c                                 :      16        2        1
linux/net/core/datagram.c                           :       8        1        1
linux/net/core/filter.c                             :       8        1        1
linux/net/ipv4/af_inet.c                            :      54        4       22
linux/net/ipv4/icmp.c                               :      11        2        2
linux/net/ipv4/ip_fw.c                              :      93       20        7
linux/net/ipv4/ip_options.c                         :      16        1        2
linux/net/ipv4/ipmr.c                               :      17        2        2
linux/net/ipv4/tcp.c                                :      16        2        1
linux/net/ipv4/tcp_input.c                          :     168       91       13
linux/net/ipv4/tcp_ipv4.c                           :      35        6        2
linux/net/ipv4/tcp_output.c                         :      20        6        1
linux/net/ipv4/tcp_timer.c                          :      25        3        6
linux/net/ipv6/icmp.c                               :      24        3        1
linux/net/ipv6/tcp_ipv6.c                           :      36        7        2
linux/net/irda/Config.in                            :      54       20       23
linux/net/irda/af_irda.c                            :     488      276       33
linux/net/irda/crc.c                                :      19        4        4
linux/net/irda/discovery.c                          :     104       42       17
linux/net/irda/ircomm/ircomm_common.c               :     561      124      116
linux/net/irda/ircomm/irvtd_driver.c                :     470      129       56
linux/net/irda/irda_device.c                        :     524      320       34
linux/net/irda/iriap.c                              :     225       42       38
linux/net/irda/iriap_event.c                        :      24        4        4
linux/net/irda/irlan/irlan_client.c                 :     213       43       41
linux/net/irda/irlan/irlan_client_event.c           :      48        6        6
linux/net/irda/irlan/irlan_common.c                 :     627      177       97
linux/net/irda/irlan/irlan_eth.c                    :     316       78      100
linux/net/irda/irlan/irlan_event.c                  :      41        8        8
linux/net/irda/irlan/irlan_filter.c                 :      78       15        9
linux/net/irda/irlan/irlan_provider.c               :     211       86       35
linux/net/irda/irlan/irlan_provider_event.c         :      50        4       10
linux/net/irda/irlap.c                              :    1069      273      273
linux/net/irda/irlap_comp.c                         :      27        4        4
linux/net/irda/irlap_event.c                        :     467       82      107
linux/net/irda/irlap_frame.c                        :      77        7       20
linux/net/irda/irlmp.c                              :     259       77       57
linux/net/irda/irlmp_frame.c                        :     155       32       30
linux/net/irda/irlpt/irlpt_cli.c                    :      79       12       12
linux/net/irda/irlpt/irlpt_cli_fsm.c                :      27        6        6
linux/net/irda/irlpt/irlpt_common.c                 :      32        6        6
linux/net/irda/irlpt/irlpt_srvr.c                   :     115       25        4
linux/net/irda/irmod.c                              :      87       24        8
linux/net/irda/irproc.c                             :     104       26       21
linux/net/irda/irsysctl.c                           :      19        4        4
linux/net/irda/irttp.c                              :     427       73       83
linux/net/irda/qos.c                                :      27        6        5
linux/net/irda/wrapper.c                            :     412      178      158
linux/net/netlink/af_netlink.c                      :      17        2        2
linux/net/netlink/netlink_dev.c                     :       8        1        1
-- 
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.
#!/bin/sh
# this is part 02 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
X Note that a packet can be queued after write()ing but not available to be
X read(); this typically happens when a SCSI read command is issued while
-the data is being retreaved.
+the data is being retrieved.
X Poll() is per file descriptor unless SG_SET_MERGE_FD is set in which case
X it is per device.
X 
X 
-fcntl
------
+fcntl(int sg_fd, int cmd) or fcntl(int sg_fd, int cmd, long arg)
+----------------------------------------------------------------
X There are several uses for this system call in association with a sg
-file descriptor. The first pseudo code shows code that is useful for
+file descriptor. The following pseudo code shows code that is useful for
X scanning the sg devices, taking care not to be caught in a wait for
X an O_EXCL lock by another process, and when the appropriate device is
-found switching to normal blocked io. A working example of this logic
-is in the sg_scan.c utility program.
+found, switching to normal blocked io. A working example of this logic
+is in the sg_scan utility program.
X 
X open("/dev/sga", O_RDONLY | O_NONBLOCK)
X /* check device, EBUSY means some other process has O_EXCL lock on it */
-/* one the device you want is found then ... */
+/* when the device you want is found then ... */
X flags = fcntl(sg_fd, F_GETFL)
X fcntl(sg_fd, F_SETFL, flags & (~ O_NONBLOCK))
-/* for simple apps is is easier to use normal blocked io */
+/* since, for simple apps, it is easier to use normal blocked io */
X 
X 
X Some work has to be done in Linux to set up for asynchronous notification.
-This is a non-blocking mode of operation in which when the driver receives
+This is a non-blocking mode of operation in which, when the driver receives
X data back from a device so that a read() can be done, it sends a SIGPOLL
X (aka SIGIO) signal to the owning process. A working example of this logic
-is in the sg_poll.c test program.
+is in the sg_poll test program.
X 
X sigemptyset(&sig_set)
X sigaddset(&sig_set, SIGPOLL)
@@ -634,3 +641,91 @@
X 
X Utility and Test Programs
X =========================
+See the README file in the sg_utils<date>.tgz tarball. At the time of
+writing this was sg_utils990527.tgz .
+
+Briefly, that tarball contains the following utilities:
+sg_dd512        'dd' like program that assumes 512 byte blocks size
+sg_dd2048       'dd' like program that assumes 2048 byte blocks size
+sgq_dd512       like 'sg_dd512' but does command queuing on "if"
+sg_scan         outputs information (optionally Inquiry) on SCSI devices
+sg_rbuf         tests SCSI bus transfer speed (without physical IO)
+sg_whoami       outputs info (optionally capacity) of given SCSI device
+sginfo          outputs "mode" information about SCSI devices (it is a
+                  re-port of the scsiinfo program onto the sg interface)
+
+It also contains the following test programs:
+sg_debug        outputs sg driver state to console/log file
+sg_poll         tests asynchronous notification
+sg_inquiry      does a SCSI Inquiry command (from original HOWTO)
+sg_tst_med      checks presence of media (from original HOWTO)
+
+There are also 2 source files (sg_err.[hc]) for outputting and categorizing
+SCSI 2 errors and warnings. This code is used by most of the above
+utility and test programs.
+
+The following programs: sg_dd512, sg_dd2048, sg_scan, sg_rbuf, sg_tst_med, 
+sg_inquiry and sginfo, can be compiled either for this new sg driver _or_
+the original sg driver.
+
+
+Header files
+============
+User applications need to find the correct "sg.h" header file matching
+their kernel in order to write code using the sg device driver. This is 
+sometimes more difficult than it should be. The correct "sg.h" will usually
+be found at /usr/src/linux/include/scsi/sg.h . Another important header 
+file is "scsi.h" which will be in the same directory.
+
+Several distributions have taken their own copies of these files and placed
+them in /usr/include/scsi which is where "#include <scsi/sg.h>" would go
+looking. The directory /usr/include/scsi _should_ be a symbolic link to
+/usr/src/linux/include/scsi/ . It was is Redhat 5.1 and 5.2 but it is
+not is Redhat 6.0 . Some other distributions have the same problem. To
+solve this (as root) do the following:
+
+# cd /usr/include
+# mv scsi scsi_orig
+# ln -s ../src/linux/include/scsi scsi
+
+This doesn't seem to be a problem with /usr/include/linux (at least in
+Redhat where it is a symbolic link) so it is hard to understand why
+/usr/include/scsi is defined the way it is. The fact the
+/usr/include/linux is a symbolic link opens up the following solution
+proposed by the author of cdparanoia (Monty):
+#include <linux/../scsi/sg.h>
+
+
+Extra information in scsi-generic_long.txt
+==========================================
+This document is an abridged form of a more comprehensive document called
+scsi-generic_long.txt (see www.torque.net/sg/p/scsi-generic_long.txt).
+
+The longer document contains additional sections on:
+   - memory issues
+   - ioctl()s in common with sd, st + sr
+   - distinguishing the original from the new driver
+   - SG_BIG_BUFF and friends
+   - shortcomings
+   - future directions
+   - an appendix with some SCSI 2 information in it
+
+
+Conclusion
+==========
+The SCSI generic packet device driver attempts to make as few assumptions
+as possible about the device it is connected to while giving applications
+using it as much flexibility as possible on the SCSI command level. Sg
+needs to hide the "messy" kernel related details while protecting
+the integrity of the kernel against sg "abuse". Some of these aims are
+contradictory and some compromises need to be made. For example: should
+a sg based application be able to reset a SCSI bus when that could cause
+collateral damage to a disk holding the root file system? There is no
+easy answer to this and many other related questions.
+
+If you have any suggestion about sg (or improving (the accuracy of) this
+document) please contact me.
+
+
+Douglas Gilbert
+dgil...@interlog.com
diff -u --recursive --new-file v2.2.9/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330
--- v2.2.9/linux/Documentation/sound/CMI8330	Wed Mar 10 15:29:44 1999
+++ linux/Documentation/sound/CMI8330	Wed May 26 09:29:42 1999
@@ -1,46 +1,48 @@
-How to enable CMI 8330 soundchip on Linux
+How to enable CMI 8330 (SOUNDPRO) soundchip on Linux
X ------------------------------------------
X Stefan Laudat <Stefan...@asit.ro>
X 
-Hello folks, 
-	
-	The CMI8330 soundchip is a very small chip found on many recent 
-	motherboards. In order to use it you just have to use a proper 
-        isapnp.conf and a little bit of patience. 
+[Note: The CMI 8338 is unrelated and right now unsupported]
+
X 	
-	Of course you will have to compile kernel sound support as module, 
-        as shown below:
+	In order to use CMI8330 under Linux  you just have to use a proper isapnp.conf, a good isapnp and a little bit of patience.  I use isapnp 1.17, but
+you may get a better one I guess at http://www.roestock.demon.co.uk/isapnptools/.
+
+	Of course you will have to compile kernel sound support as module, as shown below:
X 
X CONFIG_SOUND=m
X CONFIG_SOUND_OSS=m
X CONFIG_SOUND_SB=m
X CONFIG_SOUND_ADLIB=m
X CONFIG_SOUND_MPU401=m
-# Just for fun :)
+# Mikro$chaft sound system (kinda useful here ;))	
X CONFIG_SOUND_MSS=m
X 
X 	The /etc/isapnp.conf file will be:
X 
X <snip below>
X 
+
X (READPORT 0x0203)
X (ISOLATE PRESERVE)
X (IDENTIFY *)
X (VERBOSITY 2)
X (CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
X (VERIFYLD N)
+
+
X # WSS 
X 
X (CONFIGURE CMI0001/16777472 (LD 0
X (IO 0 (SIZE 8) (BASE 0x0530))
X (IO 1 (SIZE 8) (BASE 0x0388))
-(INT 0 (IRQ 5 (MODE +E)))
+(INT 0 (IRQ 7 (MODE +E)))
X (DMA 0 (CHANNEL 0))
X (NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}")
X (ACT Y)
X ))
X 
-# Control device ? 
+# MPU
X 
X (CONFIGURE CMI0001/16777472 (LD 1
X (IO 0 (SIZE 2) (BASE 0x0330))
@@ -57,10 +59,11 @@
X (ACT Y)
X ))
X 
-#  SB... 
+# SoundBlaster 
+ 
X (CONFIGURE CMI0001/16777472 (LD 3
X (IO 0 (SIZE 16) (BASE 0x0220))
-(INT 0 (IRQ 7 (MODE +E)))
+(INT 0 (IRQ 5 (MODE +E)))
X (DMA 0 (CHANNEL 1))
X (DMA 1 (CHANNEL 5))
X (NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}")
@@ -74,13 +77,22 @@
X 
X 	The module sequence is trivial:
X 
-/sbin/modprobe sound
-# You need to load the ad1848 module first. That matters, otherwise the 
-# chip falls into soundblaster compatibility and you won't get it back out
-/sbin/insmod ad1848 io=0x530 dma=0 irq=5 soundpro=1
+/sbin/insmod soundcore
+/sbin/insmod sound
X /sbin/insmod uart401
-/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
-/sbin/insmod mpu401 io=0x330
-/sbin/insmod opl3 io=0x388
+# insert this first
+/sbin/insmod ad1848 io=0x530 irq=7 dma=0 soundpro=1
+# The sb module is an alternative to the ad1848 (Microsoft Sound System)
+# Anyhow, this is full duplex and has MIDI
+/sbin/insmod sb io=0x220 dma=1 dma16=5 irq=5 mpu_io=0x330
+
+
X 
-	The soundchip is now fully initialized. Enjoy it.
+Alma Chao <ely...@ethereal.torsion.org> suggests the following /etc/conf.modules:
+
+alias sound ad1848
+alias synth0 opl3
+options ad1848 io=0x530 irq=7 dma=0 soundpro=1
+options opl3 io=0x388
+
+	
diff -u --recursive --new-file v2.2.9/linux/Documentation/svga.txt linux/Documentation/svga.txt
--- v2.2.9/linux/Documentation/svga.txt	Thu Jul 16 18:09:22 1998
+++ linux/Documentation/svga.txt	Fri May 14 12:47:07 1999
@@ -1,5 +1,5 @@
-		       Video Mode Selection Support 2.11
-	      (c) 1995--1997 Martin Mares, <m...@k332.feld.cvut.cz>
+		       Video Mode Selection Support 2.13
+		    (c) 1995--1999 Martin Mares, <m...@ucw.cz>
X --------------------------------------------------------------------------------
X 
X 1. Intro
@@ -9,6 +9,11 @@
X to usage of the BIOS, the selection is limited to boot time (before the
X kernel decompression starts) and works only on 80X86 machines.
X 
+   **  Short intro for the impatient: Just use vga=ask for the first time,
+   **  enter `scan' on the video mode prompt, pick the mode you want to use,
+   **  remember its mode ID (the four-digit hexadecimal number) and then
+   **  set the vga parameter to this number (converted to decimal first).
+
X    The video mode to be used is selected by a kernel parameter which can be
X specified in the kernel Makefile (the SVGA_MODE=... line) or by the "vga=..."
X option of LILO (or some other boot loader you use) or by the "vidmode" utility
@@ -268,3 +273,4 @@
X 		- Removed the doc section describing adding of new probing
X 		  functions as I try to get rid of _all_ hardware probing here.
X 2.12 (25-May-98)- Added support for VESA frame buffer graphics.
+2.13 (14-May-99)- Minor documentation fixes.
diff -u --recursive --new-file v2.2.9/linux/Documentation/video4linux/API.html linux/Documentation/video4linux/API.html
--- v2.2.9/linux/Documentation/video4linux/API.html	Fri Jan  8 22:35:59 1999
+++ linux/Documentation/video4linux/API.html	Mon Jun  7 16:13:07 1999
@@ -1,6 +1,9 @@
X <HTML><HEAD>
-<TITLE>Video4Linux Kernel API Reference v0.1:19980516</TITLE>
+<TITLE>Video4Linux Kernel API Reference v0.1:19990430</TITLE>
X </HEAD>
+<! Revision History: >
+<!   4/30/1999 - Fred Gleason (fr...@wava.com)>
+<! Documented extensions for the Radio Data System (RDS) extensions >
X <BODY bgcolor="#ffffff">
X <H3>Devices</H3>
X Video4Linux provides the following sets of device files. These live on the
@@ -117,7 +120,7 @@
X </TABLE>
X <P>
X Merely setting the window does not enable capturing. Overlay capturing
-is activatied by passing the <b>VIDIOCCAPTURE</b> ioctl a value of 1, and
+is activated by passing the <b>VIDIOCCAPTURE</b> ioctl a value of 1, and
X disabled by passing it a value of 0. 
X <P>
X Some capture devices can capture a subfield of the image they actually see.
@@ -150,7 +153,7 @@
X nature of the channel itself.
X <P>
X The <b>VIDIOCSCHAN</b> ioctl takes an integer argument and switches the
-capture to this input. It is not defined whether paramters such as colour
+capture to this input. It is not defined whether parameters such as colour
X settings or tuning are maintained across a channel switch. The caller should
X maintain settings as desired for each channel. (This is reasonable as 
X different video inputs may have different properties).
@@ -249,6 +252,8 @@
X <TR><TD><b>VIDEO_TUNER_LOW</b><TD>Frequency is in a lower range</TD>
X <TR><TD><b>VIDEO_TUNER_NORM</b><TD>The norm for this tuner is settable</TD>
X <TR><TD><b>VIDEO_TUNER_STEREO_ON</b><TD>The tuner is seeing stereo audio</TD>
+<TR><TD><b>VIDEO_TUNER_RDS_ON</b><TD>The tuner is seeing a RDS datastream</TD>
+<TR><TD><b>VIDEO_TUNER_MBS_ON</b><TD>The tuner is seeing a MBS datastream</TD>
X </TABLE>
X <P>
X The following modes are defined
@@ -349,6 +354,21 @@
X <TR><TD><b>teletext</b><TD>Teletext device</TD>
X </TABLE>
X <P>
-
+<H3>RDS Datastreams</H3>
+For radio devices that support it, it is possible to receive Radio Data
+System (RDS) data by means of a read() on the device.  The data is packed in
+groups of three, as follows:
+<TABLE>
+<TR><TD>First Octet</TD><TD>Least Siginificant Byte of RDS Block</TD></TR>
+<TR><TD>Second Octet</TD><TD>Most Siginificant Byte of RDS Block
+<TR><TD>Third Octet</TD><TD>Bit 7:</TD><TD>Error bit.  Indicates that
+an uncorrectable error occured during reception of this block.</TD></TR>
+<TR><TD> </TD><TD>Bit 6:</TD><TD>Corrected bit.  Indicates that  
+an error was corrected for this data block.</TD></TR>
+<TR><TD> </TD><TD>Bits 5-3:</TD><TD>Reeived Offset.  Indicates the  
+offset received by the sync system.</TD></TR>
+<TR><TD> </TD><TD>Bits 2-0:</TD><TD>Offset Name.  Indicates the  
+offset applied to this data.</TD></TR>
+</TABLE>
X </BODY>
X </HTML>
diff -u --recursive --new-file v2.2.9/linux/Documentation/video4linux/bttv/CONTRIBUTORS linux/Documentation/video4linux/bttv/CONTRIBUTORS
--- v2.2.9/linux/Documentation/video4linux/bttv/CONTRIBUTORS	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/bttv/CONTRIBUTORS	Wed Jun  2 11:29:27 1999
@@ -3,7 +3,7 @@
X Michael Chu <mm...@pobox.com>
X   AverMedia fix and more flexible card recognition
X 
-Alan Cox <al...@cymru.net>
+Alan Cox <al...@redhat.com>
X   Video4Linux interface and 2.1.x kernel adaptation
X 
X Chris Kleitsch
diff -u --recursive --new-file v2.2.9/linux/Documentation/video4linux/bttv/PROBLEMS linux/Documentation/video4linux/bttv/PROBLEMS
--- v2.2.9/linux/Documentation/video4linux/bttv/PROBLEMS	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/bttv/PROBLEMS	Mon Jun  7 16:13:07 1999
@@ -17,9 +17,9 @@
X   If this 64MB area overlaps the IO memory of the Bt848 you also have to
X   remap this. E.g.: insmod bttv vidmem=0xfb0 remap=0xfa0
X 
-  If the videomemory is found at the right place and there are no address
-  conflicts but still no picture (or the computer even crashes.),
-  try disabling features of your PCI chipset in the BIOS Setup.
+  If the video memory is found at the right place and there are no address
+  conflicts but still no picture (or the computer even crashes),
+  try disabling features of your PCI chipset in the BIOS setup.
X 
X   Frank Kapahnke <fr...@kapahnke.prima.ruhr.de> also reported that problems
X   with his S3 868 went away when he upgraded to XFree 3.2.
@@ -50,13 +50,13 @@
X   
X   Disable backing store by starting X with the option "-bs"
X 
-- When using 32bpp in XFree or 24+8bpp mode in AccelX 3.1 the system
+- When using 32 bpp in XFree or 24+8bpp mode in AccelX 3.1 the system
X   can sometimes lock up if you use more than 1 bt848 card at the same time.
X   You will always get pixel errors when e.g. using more than 1 card in full
X   screen mode. Maybe we need something faster than the PCI bus ...
X 
X 
-- Some S3 cards and the Matrox Mystique will produce pixel erros with
-  full resolution in 32bit mode.
+- Some S3 cards and the Matrox Mystique will produce pixel errors with
+  full resolution in 32-bit mode.
X 
-- Some video cards have problems with Accelerated X 4.1
\ No newline at end of file
+- Some video cards have problems with Accelerated X 4.1
diff -u --recursive --new-file v2.2.9/linux/Documentation/video4linux/bttv/README.RADIO linux/Documentation/video4linux/bttv/README.RADIO
--- v2.2.9/linux/Documentation/video4linux/bttv/README.RADIO	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/bttv/README.RADIO	Mon Jun  7 16:13:07 1999
@@ -6,7 +6,7 @@
X 
X So you should have TV with (stereo) sound now.  Radio does _not_ work.
X It probably does not work with sat receivers. I can't test this and
-therefore hav'nt added support for it yet. If someone needs this and
+therefore have not added support for it yet. If someone needs this and
X can help testing the sat stuff, drop me a note.
X 
X   Gerd
diff -u --recursive --new-file v2.2.9/linux/Documentation/video4linux/bttv/README.WINVIEW linux/Documentation/video4linux/bttv/README.WINVIEW
--- v2.2.9/linux/Documentation/video4linux/bttv/README.WINVIEW	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.WINVIEW	Mon Jun  7 16:13:07 1999
@@ -0,0 +1,33 @@
+
+Support for the Leadtek WinView 601 TV/FM by Jon Tombs <j...@gte.esi.us.es>
+
+This card is basically the same as all the rest (Bt484A, Philips tuner),
+the main difference is that they have attached a programmable attenuator to 3
+GPIO lines in order to give some volume control. They have also stuck an
+infra-red remote control decoded on the board, I will add support for this
+when I get time (it simple generates an interrupt for each key press, with
+the key code is placed in the GPIO port).
+
+I don't yet have any application to test the radio support. The tuner
+frequency setting should work but it is possible that the audio multiplexer
+is wrong. If it doesn't work, send me email.
+
+
+- No Thanks to Leadtek they refused to answer any questions about their
+hardware. The driver was written by visual inspection of the card. If you
+use this driver, send an email insult to them, and tell them you won't
+continue buying their hardware unless they support Linux.
+
+- Little thanks to Princeton Technology Corp (http://www.princeton.com.tw)
+who make the audio attenuator. Their publicly available data-sheet available
+on their web site doesn't include the chip programming information! Hidden
+on their server are the full data-sheets, but don't ask how I found it.
+
+To use the driver I use the following options, the tuner and pll settings might
+be different in your country
+
+insmod videodev
+insmod i2c scan=1 i2c_debug=0 verbose=0
+insmod tuner type=1 debug=0
+insmod bttv  pll=1 radio=1 card=17
+
diff -u --recursive --new-file v2.2.9/linux/Documentation/video4linux/bttv/THANKS linux/Documentation/video4linux/bttv/THANKS
--- v2.2.9/linux/Documentation/video4linux/bttv/THANKS	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/bttv/THANKS	Mon Jun  7 16:13:07 1999
@@ -17,7 +17,7 @@
X   components on their cards. (E.g. how the tuner type is detected)
X   Without their card I could not have debugged the NTSC mode.
X 	
-- Hauppauge for telling how the sound input is selected and what compenents
+- Hauppauge for telling how the sound input is selected and what components
X   they do and will use on their radio cards.
X   Also many thanks for faxing me the FM1216 data sheet.
X 
diff -u --recursive --new-file v2.2.9/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.9/linux/MAINTAINERS	Tue May 11 13:10:27 1999
+++ linux/MAINTAINERS	Thu Jun  3 08:26:38 1999
@@ -385,6 +385,11 @@
X W:	http://www.rustcorp.com/linux/ipchains
X S:	Supported
X 
+IP MASQUERADING:
+P:	Juanjo Ciarlante
+M:	jjci...@raiz.uncu.edu.ar
+S:	Maintained
+
X IPX/SPX NETWORK LAYER
X P:	Jay Schulist
X M:	Jay Schulist <Jay.Sc...@spacs.k12.wi.us>
diff -u --recursive --new-file v2.2.9/linux/Makefile linux/Makefile
--- v2.2.9/linux/Makefile	Thu May 13 23:10:29 1999
+++ linux/Makefile	Fri May 28 18:10:19 1999
@@ -1,6 +1,6 @@
X VERSION = 2
X PATCHLEVEL = 2
-SUBLEVEL = 9
+SUBLEVEL = 10
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/)
diff -u --recursive --new-file v2.2.9/linux/README linux/README
--- v2.2.9/linux/README	Fri Jan  8 22:36:00 1999
+++ linux/README	Sun May 30 10:17:03 1999
@@ -32,11 +32,11 @@
X  - There is a lot of documentation available both in electronic form on
X    the Internet and in books, both Linux-specific and pertaining to
X    general UNIX questions.  I'd recommend looking into the documentation
-   subdirectories on any Linux ftp site for the LDP (Linux Documentation
+   subdirectories on any Linux FTP site for the LDP (Linux Documentation
X    Project) books.  This README is not meant to be documentation on the
X    system: there are much better sources available.
X 
- - There are various readme's in the kernel Documentation/ subdirectory:
+ - There are various README files in the Documentation/ subdirectory:
X    these typically contain kernel-specific installation notes for some 
X    drivers for example. See ./Documentation/00-INDEX for a list of what
X    is contained in each file.  Please read the Changes file, as it
@@ -219,7 +219,7 @@
X    isn't anyone listed there, then the second best thing is to mail
X    them to me (torv...@transmeta.com), and possibly to any other
X    relevant mailing-list or to the newsgroup.  The mailing-lists are
-   useful especially for SCSI and NETworking problems, as I can't test
+   useful especially for SCSI and networking problems, as I can't test
X    either of those personally anyway. 
X 
X  - In all bug-reports, *please* tell what kernel you are talking about,
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.2.9/linux/arch/alpha/config.in	Tue May 11 13:10:27 1999
+++ linux/arch/alpha/config.in	Sat May 22 13:41:37 1999
@@ -142,6 +142,7 @@
X 
X if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
X 	-o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \
+	-o "$CONFIG_ALPHA_TAKARA" = "y" -o "$CONFIG_ALPHA_EB164" = "y" \
X 	-o "$CONFIG_ALPHA_MIKASA" = "y" -o "$CONFIG_ALPHA_ALCOR" = "y" \
X 	-o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \
X 	-o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \
@@ -166,7 +167,11 @@
X 	define_bool CONFIG_ALPHA_AVANTI y
X fi
X 
-bool 'Symmetric multi-processing support' CONFIG_SMP
+if [ "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" \
+	-o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_GENERIC" = "y" ]
+then
+	bool 'Symmetric multi-processing support' CONFIG_SMP
+fi
X 
X if [ "$CONFIG_PCI" = "y" ]; then
X   bool 'PCI quirks' CONFIG_PCI_QUIRKS
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.2.9/linux/arch/alpha/defconfig	Wed Mar 10 15:29:45 1999
+++ linux/arch/alpha/defconfig	Sat Jun 12 11:52:51 1999
@@ -12,12 +12,11 @@
X #
X CONFIG_MODULES=y
X # CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
X 
X #
X # General setup
X #
-CONFIG_NATIVE=y
X CONFIG_ALPHA_GENERIC=y
X # CONFIG_ALPHA_ALCOR is not set
X # CONFIG_ALPHA_XL is not set
@@ -39,12 +38,12 @@
X # CONFIG_ALPHA_P2K is not set
X # CONFIG_ALPHA_RAWHIDE is not set
X # CONFIG_ALPHA_RUFFIAN is not set
+# CONFIG_ALPHA_RX164 is not set
X # CONFIG_ALPHA_SX164 is not set
X # CONFIG_ALPHA_SABLE is not set
X # CONFIG_ALPHA_TAKARA is not set
-# CONFIG_SMP is not set
X CONFIG_PCI=y
-CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
+# CONFIG_SMP is not set
X # CONFIG_PCI_QUIRKS is not set
X CONFIG_PCI_OLD_PROC=y
X CONFIG_NET=y
@@ -88,7 +87,7 @@
X #
X # Networking options
X #
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
X # CONFIG_NETLINK is not set
X # CONFIG_FIREWALL is not set
X # CONFIG_FILTER is not set
@@ -107,7 +106,6 @@
X # (it is safe to leave these untouched)
X #
X # CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
X CONFIG_SKB_LARGE=y
X 
X #
@@ -141,6 +139,7 @@
X # SCSI low-level drivers
X #
X # CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
X # CONFIG_SCSI_AHA152X is not set
X # CONFIG_SCSI_AHA1542 is not set
X # CONFIG_SCSI_AHA1740 is not set
@@ -148,23 +147,29 @@
X # CONFIG_SCSI_ADVANSYS is not set
X # CONFIG_SCSI_IN2000 is not set
X # CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
X # CONFIG_SCSI_BUSLOGIC is not set
X # CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
X # CONFIG_SCSI_EATA_DMA is not set
X # CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
X # CONFIG_SCSI_FUTURE_DOMAIN is not set
X # CONFIG_SCSI_GDTH is not set
X # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
X # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
X # CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
X # CONFIG_SCSI_PCI2220I is not set
X # CONFIG_SCSI_PSI240I is not set
X # CONFIG_SCSI_QLOGIC_FAS is not set
X CONFIG_SCSI_QLOGIC_ISP=y
+# CONFIG_SCSI_QLOGIC_FC is not set
X # CONFIG_SCSI_SEAGATE is not set
X # CONFIG_SCSI_DC390T is not set
X # CONFIG_SCSI_T128 is not set
@@ -194,6 +199,7 @@
X # CONFIG_EEXPRESS_PRO100 is not set
X # CONFIG_NE2K_PCI is not set
X # CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
X # CONFIG_NET_POCKET is not set
X # CONFIG_FDDI is not set
X # CONFIG_DLCI is not set
@@ -202,6 +208,8 @@
X # CONFIG_NET_RADIO is not set
X # CONFIG_TR is not set
X # CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
X # CONFIG_WAN_DRIVERS is not set
X # CONFIG_LAPBETHER is not set
X # CONFIG_X25_ASY is not set
@@ -217,7 +225,7 @@
X # CONFIG_ISDN is not set
X 
X #
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# Old CD-ROM drivers (not SCSI, not IDE)
X #
X # CONFIG_CD_NO_IDESCSI is not set
X 
@@ -233,19 +241,31 @@
X CONFIG_UNIX98_PTYS=y
X CONFIG_UNIX98_PTY_COUNT=256
X CONFIG_MOUSE=y
+
+#
+# Mice
+#
X # CONFIG_ATIXL_BUSMOUSE is not set
X # CONFIG_BUSMOUSE is not set
X # CONFIG_MS_BUSMOUSE is not set
X CONFIG_PSMOUSE=y
X # CONFIG_82C710_MOUSE is not set
X # CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
X # CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
X # CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
+
+#
+# Joystick support
+#
X # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
X 
X #
X # Ftape, the floppy tape device driver
@@ -256,31 +276,43 @@
X # Filesystems
X #
X # CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
X # CONFIG_FAT_FS is not set
X # CONFIG_MSDOS_FS is not set
X # CONFIG_UMSDOS_FS is not set
X # CONFIG_VFAT_FS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
X CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
X CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
+# CONFIG_NFSD_SUN is not set
X CONFIG_SUNRPC=y
X CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
X # CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_DEVPTS_FS=y
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_BSD_DISKLABEL is not set
X # CONFIG_MAC_PARTITION is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
X # CONFIG_NLS is not set
X 
X #
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.2.9/linux/arch/alpha/kernel/alpha_ksyms.c	Tue Jan 19 11:32:50 1999
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Sat May 22 13:41:43 1999
@@ -52,6 +52,7 @@
X EXPORT_SYMBOL(local_irq_count);
X EXPORT_SYMBOL(enable_irq);
X EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(disable_irq_nosync);
X EXPORT_SYMBOL(screen_info);
X EXPORT_SYMBOL(perf_irq);
X 
@@ -170,8 +171,8 @@
X EXPORT_SYMBOL(__global_restore_flags);
X #if DEBUG_SPINLOCK
X EXPORT_SYMBOL(spin_unlock);
-EXPORT_SYMBOL(spin_lock);
-EXPORT_SYMBOL(spin_trylock);
+EXPORT_SYMBOL(debug_spin_lock);
+EXPORT_SYMBOL(debug_spin_trylock);
X #endif
X #if DEBUG_RWLOCK
X EXPORT_SYMBOL(write_lock);
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c
--- v2.2.9/linux/arch/alpha/kernel/core_cia.c	Wed Sep  9 14:51:03 1998
+++ linux/arch/alpha/kernel/core_cia.c	Sat May 22 13:41:43 1999
@@ -598,7 +598,7 @@
X {
X 	CIA_jd = *(vuip)CIA_IOC_CIA_ERR;
X 	DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd));
-	*(vuip)CIA_IOC_CIA_ERR = 0x0180;
+	*(vuip)CIA_IOC_CIA_ERR = CIA_jd;
X 	mb();
X 	return 0;
X }
@@ -698,6 +698,10 @@
X 		reason = buf;
X 		break;
X 	}
+	mb();
+	mb();  /* magic */
+	draina();
+	cia_pci_clr_err();
X 	wrmces(rdmces());	/* reset machine check pending flag */
X 	mb();
X 
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/fpreg.c linux/arch/alpha/kernel/fpreg.c
--- v2.2.9/linux/arch/alpha/kernel/fpreg.c	Tue Aug 18 22:02:02 1998
+++ linux/arch/alpha/kernel/fpreg.c	Sat May 22 13:41:47 1999
@@ -1,10 +1,10 @@
X /*
- * kernel/fpreg.c
+ * arch/alpha/kernel/fpreg.c
X  *
X  * (C) Copyright 1998 Linus Torvalds
X  */
X 
-#ifdef __alpha_cix__
+#if defined(__alpha_cix__) || defined(__alpha_fix__)
X #define STT(reg,val)  asm volatile ("ftoit $f"#reg",%0" : "=r"(val));
X #else
X #define STT(reg,val)  asm volatile ("stt $f"#reg",%0" : "=m"(val));
@@ -52,7 +52,7 @@
X 	return val;
X }
X 
-#ifdef __alpha_cix__
+#if defined(__alpha_cix__) || defined(__alpha_fix__)
X #define LDT(reg,val)  asm volatile ("itoft %0,$f"#reg : : "r"(val));
X #else
X #define LDT(reg,val)  asm volatile ("ldt $f"#reg",%0" : : "m"(val));
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S
--- v2.2.9/linux/arch/alpha/kernel/head.S	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/head.S	Sat Jun 12 11:52:52 1999
@@ -32,106 +32,27 @@
X 
X #ifdef __SMP__
X 	.align 3
-	.globl	__start_cpu
-	.ent	__start_cpu
-	/* On entry here from SRM console, the HWPCB of this processor
-	   has been loaded, and $27 contains the task pointer */
-__start_cpu:
-	.prologue 0
-	/* First order of business, load the GP */
-	br	$26,1f
-1:	ldgp	$29,0($26)
-	/* We need to get current loaded up with our first task...  */
-	mov	$27,$8
-	/* Set FEN */
-	lda	$16,1($31)
-	call_pal PAL_wrfen
-	/* ... and then we can start the processor.  */
-	jsr	$26,start_secondary
+	.globl	__smp_callin
+	.ent	__smp_callin
+	/* On entry here from SRM console, the HWPCB of the per-cpu
+	   slot for this processor has been loaded.  We've arranged
+	   for the UNIQUE value for this process to contain the PCBB
+	   of the target idle task.  */
+__smp_callin:
+	.prologue 1
+	ldgp	$29,0($27)	# First order of business, load the GP.
+
+	call_pal PAL_rduniq	# Grab the target PCBB.
+	mov	$0,$16		# Install it.
+	call_pal PAL_swpctx
+
+	lda	$8,0x3fff	# Find "current".
+	bic	$30,$8,$8
+	
+	jsr	$26,smp_callin
X 	call_pal PAL_halt
-	.end __start_cpu
+	.end __smp_callin
X #endif /* __SMP__ */
-
-	.align 3
-	.globl	wrent
-	.ent	wrent
-wrent:
-	.prologue 0
-	call_pal PAL_wrent
-	ret	($26)
-	.end wrent
-
-	.align 3
-	.globl	wrkgp
-	.ent	wrkgp
-wrkgp:
-	.prologue 0
-	call_pal PAL_wrkgp
-	ret	($26)
-	.end wrkgp
-
-	.align 3
-	.globl	wrusp
-	.ent	wrusp
-wrusp:
-	.prologue 0
-	call_pal PAL_wrusp
-	ret	($26)
-	.end wrusp
-
-	.align 3
-	.globl	rdusp
-	.ent	rdusp
-rdusp:
-	.prologue 0
-	call_pal PAL_rdusp
-	ret	($26)
-	.end rdusp
-
-	.align 3
-	.globl	rdmces
-	.ent	rdmces
-rdmces:
-	.prologue 0
-	call_pal PAL_rdmces
-	ret	($26)
-	.end rdmces
-
-	.align 3
-	.globl	wrmces
-	.ent	wrmces
-wrmces:
-	.prologue 0
-	call_pal PAL_wrmces
-	ret	($26)
-	.end wrmces
-
-	.align 3
-	.globl  whami
-	.ent    whami
-whami:
-	.prologue 0
-	call_pal PAL_whami
-	ret     ($26)
-	.end whami
- 
-	.align 3
-	.globl  wripir
-	.ent    wripir
-wripir:
-	.prologue 0
-	call_pal PAL_wripir
-	ret     ($26)
-	.end wripir
-
-	.align 3
-	.globl wrvptptr
-	.ent wrvptptr
-wrvptptr:
-	.prologue 0
-	call_pal PAL_wrvptptr
-	ret	($26)
-	.end wrvptptr
X 
X 	#
X 	# The following two functions are needed for supporting SRM PALcode
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.2.9/linux/arch/alpha/kernel/irq.c	Tue Jan 19 11:32:50 1999
+++ linux/arch/alpha/kernel/irq.c	Sat May 22 13:42:26 1999
@@ -192,13 +192,21 @@
X }
X 
X void
-disable_irq(unsigned int irq_nr)
+disable_irq_nosync(unsigned int irq_nr)
X {
X 	unsigned long flags;
X 
X 	save_and_cli(flags);
X 	mask_irq(irq_nr);
X 	restore_flags(flags);
+}
+
+void
+disable_irq(unsigned int irq_nr)
+{
+	/* This works non-SMP, and SMP until we write code to distribute
+	   interrupts to more that cpu 0.  */
+	disable_irq_nosync(irq_nr);
X }
X 
X void
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.2.9/linux/arch/alpha/kernel/process.c	Tue May 11 13:10:27 1999
+++ linux/arch/alpha/kernel/process.c	Sat May 22 13:42:29 1999
@@ -75,33 +75,46 @@
X 	return 0;
X }
X 
-static void __attribute__((noreturn))
-do_cpu_idle(void)
+#ifdef __SMP__
+void
+cpu_idle(void *unused)
X {
X 	/* An endless idle loop with no priority at all.  */
X 	current->priority = 0;
+	current->counter = -100;
+
X 	while (1) {
-		check_pgt_cache();
-		run_task_queue(&tq_scheduler);
-		current->counter = 0;
-		schedule();
-	}
-}
+		/* FIXME -- EV6 and LCA45 know how to power down
+		   the CPU.  */
X 
-#ifdef __SMP__
-void
-cpu_idle(void *unused)
-{
-	do_cpu_idle();
+		/* Although we are an idle CPU, we do not want to 
+		   get into the scheduler unnecessarily.  */
+		if (current->need_resched) {
+			schedule();
+			check_pgt_cache();
+		}
+	}
X }
X #endif
X 
X asmlinkage int
X sys_idle(void)
X {
-	if (current->pid == 0)
-        	do_cpu_idle();
-	return -EPERM;
+	if (current->pid != 0)
+		return -EPERM;
+
+	/* An endless idle loop with no priority at all.  */
+	current->priority = 0;
+	current->counter = -100;
+	init_idle();
+
+	while (1) {
+		/* FIXME -- EV6 and LCA45 know how to power down
+		   the CPU.  */
+
+		schedule();
+		check_pgt_cache();
+	}
X }
X 
X void
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.2.9/linux/arch/alpha/kernel/proto.h	Tue Feb 23 15:21:32 1999
+++ linux/arch/alpha/kernel/proto.h	Sat Jun 12 11:52:52 1999
@@ -151,6 +151,8 @@
X extern void setup_smp(void);
X extern int smp_info(char *buffer);
X extern void handle_ipi(struct pt_regs *);
+extern void smp_percpu_timer_interrupt(struct pt_regs *);
+extern int smp_boot_cpuid;
X 
X /* bios32.c */
X extern void reset_for_srm(void);
@@ -178,7 +180,7 @@
X extern void wrmces(unsigned long mces);
X extern void cserve_ena(unsigned long);
X extern void cserve_dis(unsigned long);
-extern void __start_cpu(unsigned long);
+extern void __smp_callin(unsigned long);
X 
X /* entry.S */
X extern void entArith(void);
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.2.9/linux/arch/alpha/kernel/setup.c	Wed Apr 28 11:37:29 1999
+++ linux/arch/alpha/kernel/setup.c	Sat May 22 13:42:31 1999
@@ -106,6 +106,7 @@
X WEAK(alphabook1_mv);
X WEAK(avanti_mv);
X WEAK(cabriolet_mv);
+WEAK(clipper_mv);
X WEAK(dp264_mv);
X WEAK(eb164_mv);
X WEAK(eb64p_mv);
@@ -330,6 +331,10 @@
X 
X 	/* Round it up to an even number of pages. */
X 	high = (high + PAGE_SIZE) & (PAGE_MASK*2);
+
+	/* Enforce maximum of 2GB even if there is more.  Blah.  */
+	if (high > 0x80000000UL)
+		high = 0x80000000UL;
X 	return PAGE_OFFSET + high;
X }
X 
@@ -448,11 +453,11 @@
X 	static struct alpha_machine_vector *tsunami_vecs[]  __initlocaldata =
X 	{
X 		NULL,
-		&dp264_mv,		/* dp164 */
+		&dp264_mv,		/* dp264 */
X 		&dp264_mv,		/* warhol */
X 		&dp264_mv,		/* windjammer */
X 		&monet_mv,		/* monet */
-		&dp264_mv,		/* clipper */
+		&clipper_mv,		/* clipper */
X 		&dp264_mv,		/* goldrush */
X 		&webbrick_mv,		/* webbrick */
X 		&dp264_mv,		/* catamaran */
@@ -537,6 +542,7 @@
X 		&alphabook1_mv,
X 		&avanti_mv,
X 		&cabriolet_mv,
+		&clipper_mv,
X 		&dp264_mv,
X 		&eb164_mv,
X 		&eb64p_mv,
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.2.9/linux/arch/alpha/kernel/signal.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/signal.c	Sat Jun 12 11:52:52 1999
@@ -24,6 +24,9 @@
X #include <asm/sigcontext.h>
X #include <asm/ucontext.h>
X 
+#include "proto.h"
+
+
X #define DEBUG_SIG 0
X 
X #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.2.9/linux/arch/alpha/kernel/smp.c	Tue May 11 13:10:27 1999
+++ linux/arch/alpha/kernel/smp.c	Sat Jun 12 11:52:52 1999
@@ -18,6 +18,7 @@
X #include <asm/ptrace.h>
X #include <asm/atomic.h>
X 
+#include <asm/io.h>
X #include <asm/irq.h>
X #include <asm/bitops.h>
X #include <asm/pgtable.h>
@@ -29,6 +30,8 @@
X #include <asm/unistd.h>
X 
X #include "proto.h"
+#include "irq.h"
+
X 
X #define DEBUG_SMP 0
X #if DEBUG_SMP
@@ -37,62 +40,44 @@
X #define DBGS(args)
X #endif
X 
-struct ipi_msg_flush_tb_struct {
-	volatile unsigned int flush_tb_mask;
-	union {
-		struct mm_struct *	flush_mm;
-		struct vm_area_struct *	flush_vma;
-	} p;
-	unsigned long flush_addr;
-	unsigned long flush_end;
-};
-
-static struct ipi_msg_flush_tb_struct ipi_msg_flush_tb __cacheline_aligned;
-static spinlock_t flush_tb_lock = SPIN_LOCK_UNLOCKED;
-
+/* A collection of per-processor data.  */
X struct cpuinfo_alpha cpu_data[NR_CPUS];
X 
-spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+/* A collection of single bit ipi messages.  */
+static struct {
+	unsigned long bits __cacheline_aligned;
+} ipi_data[NR_CPUS];
X 
-unsigned int boot_cpu_id = 0;
-static int smp_activated = 0;
-
-int smp_found_config = 0; /* Have we found an SMP box */
-static int max_cpus = -1;
+enum ipi_message_type {
+        IPI_RESCHEDULE,
+        IPI_CALL_FUNC,
+        IPI_CPU_STOP,
+};
X 
-unsigned int cpu_present_map = 0;
+spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
X 
-int smp_num_cpus = 1;
-int smp_num_probed = 0; /* Internal processor count */
+/* Set to a secondary's cpuid when it comes online.  */
+static unsigned long smp_secondary_alive;
X 
-int smp_threads_ready = 0;
-volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
-volatile unsigned long smp_spinning[NR_CPUS] = { 0, };
+unsigned long cpu_present_mask;	/* Which cpus ids came online.  */
X 
+static int max_cpus = -1;	/* Command-line limitation.  */
+int smp_boot_cpuid;		/* Which processor we booted from.  */
+int smp_num_probed;		/* Internal processor count */
+int smp_num_cpus = 1;		/* Number that came online.  */
+int smp_threads_ready;		/* True once the per process idle is forked. */
X cycles_t cacheflush_time;
X 
-unsigned int prof_multiplier[NR_CPUS];
-unsigned int prof_counter[NR_CPUS];
-
-volatile int ipi_bits[NR_CPUS] __cacheline_aligned;
-
-unsigned long boot_cpu_palrev;
-
-volatile int smp_commenced = 0;
-volatile int smp_processors_ready = 0;
-
-volatile int cpu_number_map[NR_CPUS];
-volatile int cpu_logical_map[NR_CPUS];
+int cpu_number_map[NR_CPUS];
+int __cpu_logical_map[NR_CPUS];
X 
X extern void calibrate_delay(void);
-extern struct thread_struct * original_pcb_ptr;
-
-static void smp_setup_percpu_timer(void);
-static void secondary_cpu_start(int, struct task_struct *);
-static void send_cpu_msg(char *, int);
+extern asmlinkage void entInt(void);
X 
-/* Process bootcommand SMP options, like "nosmp" and "maxcpus=" */
+
+/*
+ * Process bootcommand SMP options, like "nosmp" and "maxcpus=".
+ */
X void __init
X smp_setup(char *str, int *ints)
X {
@@ -102,100 +87,87 @@
X 		max_cpus = 0;
X }
X 
-static void __init
-smp_store_cpu_info(int id)
+/*
+ * Called by both boot and secondaries to move global data into
+ *  per-processor storage.
+ */
+static inline void __init
+smp_store_cpu_info(int cpuid)
X {
-	/* This is it on Alpha, so far. */
-	cpu_data[id].loops_per_sec = loops_per_sec;
+	cpu_data[cpuid].loops_per_sec = loops_per_sec;
X }
X 
-void __init
-smp_commence(void)
+/*
+ * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
+ */
+static inline void __init
+smp_setup_percpu_timer(int cpuid)
X {
-	/* Lets the callin's below out of their loop. */
-	mb();
-	smp_commenced = 1;
+	cpu_data[cpuid].prof_counter = 1;
+	cpu_data[cpuid].prof_multiplier = 1;
+
+#ifdef NOT_YET_PROFILING
+	load_profile_irq(mid_xlate[cpu], lvl14_resolution);
+	if (cpu == smp_boot_cpuid)
+		enable_pil_irq(14);
+#endif
X }
X 
+/*
+ * Where secondaries begin a life of C.
+ */
X void __init
X smp_callin(void)
X {
X 	int cpuid = hard_smp_processor_id();
X 
X 	DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state));
-#ifdef HUH
-	local_flush_cache_all();
-	local_flush_tlb_all();
-#endif
-#if 0
-	set_irq_udt(mid_xlate[boot_cpu_id]);
-#endif
+
+	/* Turn on machine checks.  */
+	wrmces(7);
+
+	/* Set trap vectors.  */
+	trap_init();
+
+	/* Set interrupt vector.  */
+	wrent(entInt, 0);
+
+	/* Setup the scheduler for this processor.  */
+	init_idle();
X 
X 	/* Get our local ticker going. */
-	smp_setup_percpu_timer();
+	smp_setup_percpu_timer(cpuid);
X 
-#if 0
+	/* Must have completely accurate bogos.  */
+	__sti();
X 	calibrate_delay();
-#endif
X 	smp_store_cpu_info(cpuid);
-#ifdef HUH
-	local_flush_cache_all();
-	local_flush_tlb_all();
-#endif
X 
X 	/* Allow master to continue. */
-	set_bit(cpuid, (unsigned long *)&cpu_callin_map[cpuid]);
-#ifdef HUH
-	local_flush_cache_all();
-	local_flush_tlb_all();
-#endif
-
-#ifdef NOT_YET
-	while(!task[cpuid] || current_set[cpuid] != task[cpuid])
-	        barrier();
-#endif
-
-#ifdef HUH
-	local_flush_cache_all();
-	local_flush_tlb_all();
-#endif
-#if 0
-	__sti();
-#endif
-}
+	wmb();
+	smp_secondary_alive = cpuid;
X 
-asmlinkage int __init
-start_secondary(void *unused)
-{
-	extern asmlinkage void entInt(void);
-	extern void paging_init_secondary(void);
+	/* Wait for the go code.  */
+	while (!smp_threads_ready)
+		barrier();
X 
-	wrmces(7);
-	paging_init_secondary();
-	trap_init();
-	wrent(entInt, 0);
+	DBGS(("smp_callin: commencing CPU %d current %p\n",
+	      cpuid, current));
X 
-	smp_callin();
-	while (!smp_commenced)
-		barrier();
-#if 1
-	printk("start_secondary: commencing CPU %d current %p\n",
-	       hard_smp_processor_id(), current);
-#endif
+	/* Do nothing.  */
X 	cpu_idle(NULL);
X }
X 
+
+/*
+ * Rough estimation for SMP scheduling, this is the number of cycles it
+ * takes for a fully memory-limited process to flush the SMP-local cache.
+ *
+ * We are not told how much cache there is, so we have to guess.
+ */
X static void __init
X smp_tune_scheduling (void)
X {
-	/*
-	 * Rough estimation for SMP scheduling, this is the number of
-	 * cycles it takes for a fully memory-limited process to flush
-	 * the SMP-local cache.
-	 *
-	 * We are not told how much cache there is, so we have to guess.
-	 */
-
X 	struct percpu_struct *cpu;
X 	unsigned long on_chip_cache;
X 	unsigned long freq;
@@ -231,298 +203,18 @@
X 	cacheflush_time = freq / 1024 * on_chip_cache / 5000;
X }
X 
-
X /*
- *      Cycle through the processors sending START msgs to boot each.
+ * Send a message to a secondary's console.  "START" is one such
+ * interesting message.  ;-)
X  */
-void __init
-smp_boot_cpus(void)
-{
-	int cpucount = 0;
-	int i, first, prev;
-
-	printk("Entering SMP Mode.\n");
-
-#if 0
-	__sti();
-#endif
-
-	for(i=0; i < NR_CPUS; i++) {
-		cpu_number_map[i] = -1;
-		cpu_logical_map[i] = -1;
-	        prof_counter[i] = 1;
-	        prof_multiplier[i] = 1;
-		ipi_bits[i] = 0;
-	}
-
-	cpu_number_map[boot_cpu_id] = 0;
-	cpu_logical_map[0] = boot_cpu_id;
-	current->processor = boot_cpu_id; /* ??? */
-
-	smp_store_cpu_info(boot_cpu_id);
-	smp_tune_scheduling();
-#ifdef NOT_YET
-	printk("CPU%d: ", boot_cpu_id);
-	print_cpu_info(&cpu_data[boot_cpu_id]);
-	set_irq_udt(mid_xlate[boot_cpu_id]);
-#endif
-	smp_setup_percpu_timer();
-#ifdef HUH
-	local_flush_cache_all();
-#endif
-	if (smp_num_probed == 1)
-		return;  /* Not an MP box. */
-
-#if NOT_YET
-	/*
-	 * If SMP should be disabled, then really disable it!
-	 */
-	if (!max_cpus)
-	{
-		smp_found_config = 0;
-	        printk(KERN_INFO "SMP mode deactivated.\n");
-	}
-#endif
-
-	for (i = 0; i < NR_CPUS; i++) {
-
-		if (i == boot_cpu_id)
-			continue;
-
-	        if (cpu_present_map & (1 << i)) {
-	                struct task_struct *idle;
-	                int timeout;
-
-	                /* Cook up an idler for this guy. */
-	                kernel_thread(start_secondary, NULL, CLONE_PID);
-	                idle = task[++cpucount];
-			if (!idle)
-				panic("No idle process for CPU %d", i);
-	                idle->processor = i;
-
-			DBGS(("smp_boot_cpus: CPU %d state 0x%lx flags 0x%lx\n",
-			      i, idle->state, idle->flags));
-
-	                /* whirrr, whirrr, whirrrrrrrrr... */
-#ifdef HUH
-	                local_flush_cache_all();
-#endif
-	                secondary_cpu_start(i, idle);
-
-	                /* wheee... it's going... wait for 5 secs...*/
-	                for (timeout = 0; timeout < 50000; timeout++) {
-				if (cpu_callin_map[i])
-					break;
-	                        udelay(100);
-	                }
-	                if (cpu_callin_map[i]) {
-				/* Another "Red Snapper". */
-				cpu_number_map[i] = cpucount;
-	                        cpu_logical_map[cpucount] = i;
-	                } else {
-				cpucount--;
-	                        printk("smp_boot_cpus: Processor %d"
-				       " is stuck 0x%lx.\n", i, idle->flags);
-	                }
-	        }
-	        if (!(cpu_callin_map[i])) {
-			cpu_present_map &= ~(1 << i);
-	                cpu_number_map[i] = -1;
-	        }
-	}
-#ifdef HUH
-	local_flush_cache_all();
-#endif
-	if (cpucount == 0) {
-		printk("smp_boot_cpus: ERROR - only one Processor found.\n");
-	        cpu_present_map = (1 << smp_processor_id());
-	} else {
-		unsigned long bogosum = 0;
-	        for (i = 0; i < NR_CPUS; i++) {
-			if (cpu_present_map & (1 << i))
-				bogosum += cpu_data[i].loops_per_sec;
-	        }
-	        printk("smp_boot_cpus: Total of %d Processors activated"
-		       " (%lu.%02lu BogoMIPS).\n",
-	               cpucount + 1,
-	               (bogosum + 2500)/500000,
-	               ((bogosum + 2500)/5000)%100);
-	        smp_activated = 1;
-	        smp_num_cpus = cpucount + 1;
-	}
-
-	/* Setup CPU list for IRQ distribution scheme. */
-	first = prev = -1;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_present_map & (1 << i)) {
-			if (first == -1)
-				first = i;
-			if (prev != -1)
-				cpu_data[i].next = i;
-	                prev = i;
-	        }
-	}
-	cpu_data[prev].next = first;
-
-	/* Ok, they are spinning and ready to go. */
-	smp_processors_ready = 1;
-}
-
-static void __init
-smp_setup_percpu_timer(void)
-{
-	int cpu = smp_processor_id();
-
-	prof_counter[cpu] = prof_multiplier[cpu] = 1;
-#ifdef NOT_YET
-	load_profile_irq(mid_xlate[cpu], lvl14_resolution);
-	if (cpu == boot_cpu_id)
-		enable_pil_irq(14);
-#endif
-}
-
-extern void update_one_process(struct task_struct *p, unsigned long ticks,
-	                       unsigned long user, unsigned long system,
-			       int cpu);
-
-void
-smp_percpu_timer_interrupt(struct pt_regs *regs)
-{
-	int cpu = smp_processor_id();
-
-#ifdef NOT_YET
-	clear_profile_irq(mid_xlate[cpu]);
-	if(!user_mode(regs))
-		alpha_do_profile(regs->pc);
-#endif
-
-	if (!--prof_counter[cpu]) {
-		int user = user_mode(regs);
-	        if (current->pid) {
-			update_one_process(current, 1, user, !user, cpu);
-
-	                if (--current->counter < 0) {
-				current->counter = 0;
-	                        current->need_resched = 1;
-	                }
-
-	                spin_lock(&ticker_lock);
-	                if (user) {
-				if (current->priority < DEF_PRIORITY) {
-					kstat.cpu_nice++;
-					kstat.per_cpu_nice[cpu]++;
-				} else {
-					kstat.cpu_user++;
-					kstat.per_cpu_user[cpu]++;
-				}
-	                } else {
-				kstat.cpu_system++;
-				kstat.per_cpu_system[cpu]++;
-	                }
-	                spin_unlock(&ticker_lock);
-	        }
-	        prof_counter[cpu] = prof_multiplier[cpu];
-	}
-}
-
-int __init
-setup_profiling_timer(unsigned int multiplier)
-{
-#ifdef NOT_YET
-	int i;
-	unsigned long flags;
-
-	/* Prevent level14 ticker IRQ flooding. */
-	if((!multiplier) || (lvl14_resolution / multiplier) < 500)
-	        return -EINVAL;
-
-	save_and_cli(flags);
-	for(i = 0; i < NR_CPUS; i++) {
-	        if(cpu_present_map & (1 << i)) {
-	                load_profile_irq(mid_xlate[i], lvl14_resolution / multip
-lier);
-	                prof_multiplier[i] = multiplier;
-	        }
-	}
-	restore_flags(flags);
-
-	return 0;
-
-#endif
-  return -EINVAL;
-}
-
-/* Only broken Intel needs this, thus it should not even be
-   referenced globally.  */
-
-void __init
-initialize_secondary(void)
-{
-}
-
-static void __init
-secondary_cpu_start(int cpuid, struct task_struct *idle)
-{
-	struct percpu_struct *cpu;
-	int timeout;
-	  
-	cpu = (struct percpu_struct *)
-		((char*)hwrpb
-		 + hwrpb->processor_offset
-		 + cpuid * hwrpb->processor_size);
-
-	/* Set context to idle thread this CPU will use when running
-	   assumption is that the idle thread is all set to go... ??? */
-	memcpy(&cpu->hwpcb[0], &idle->tss, sizeof(struct pcb_struct));
-	cpu->hwpcb[4] = cpu->hwpcb[0]; /* UNIQUE set to KSP ??? */
-
-	DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx\n",
-	      cpu->hwpcb[0], cpu->hwpcb[2], hwrpb->vptb));
-	DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
-	      cpuid, idle->state, idle->tss.pal_flags));
-
-	/* Setup HWRPB fields that SRM uses to activate secondary CPU */
-	hwrpb->CPU_restart = __start_cpu;
-	hwrpb->CPU_restart_data = (unsigned long) idle;
-
-	/* Recalculate and update the HWRPB checksum */
-	hwrpb_update_checksum(hwrpb);
-
-	/*
-	 * Send a "start" command to the specified processor.
-	 */
-
-	/* SRM III 3.4.1.3 */
-	cpu->flags |= 0x22;	/* turn on Context Valid and Restart Capable */
-	cpu->flags &= ~1;	/* turn off Bootstrap In Progress */
-	mb();
-
-	send_cpu_msg("START\r\n", cpuid);
-
-	/* now, we wait... */
-	for (timeout = 10000; !(cpu->flags & 1); timeout--) {
-		if (timeout <= 0) {
-			printk("Processor %d failed to start\n", cpuid);
-	                        /* needed for pset_info to work */
-#if 0
-			ipc_processor_enable(cpu_to_processor(cpunum));
-#endif
-			return;
-		}
-		mdelay(1);
-		barrier();
-	}
-	DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
-}
-
X static void
-send_cpu_msg(char *str, int cpuid)
+send_secondary_console_msg(char *str, int cpuid)
X {
X 	struct percpu_struct *cpu;
X 	register char *cp1, *cp2;
X 	unsigned long cpumask;
X 	size_t len;
-	int timeout;
+	long timeout;
X 
X 	cpu = (struct percpu_struct *)
X 		((char*)hwrpb
@@ -541,6 +233,7 @@
X 	memcpy(cp1, cp2, len);
X 
X 	/* atomic test and set */
+	wmb();
X 	set_bit(cpuid, &hwrpb->rxrdy);
X 
X 	if (hwrpb->txrdy & cpumask)
@@ -549,19 +242,21 @@
X 	return;
X 
X delay1:
-	for (timeout = 10000; timeout > 0; --timeout) {
+	/* Wait one second.  Note that jiffies aren't ticking yet.  */
+	for (timeout = 100000; timeout > 0; --timeout) {
X 		if (!(hwrpb->txrdy & cpumask))
X 			goto ready1;
-		udelay(100);
+		udelay(10);
X 		barrier();
X 	}
X 	goto timeout;
X 
X delay2:
-	for (timeout = 10000; timeout > 0; --timeout) {
+	/* Wait one second.  */
+	for (timeout = 100000; timeout > 0; --timeout) {
X 		if (!(hwrpb->txrdy & cpumask))
X 			goto ready2;
-		udelay(100);
+		udelay(10);
X 		barrier();
X 	}
X 	goto timeout;
@@ -572,64 +267,17 @@
X }
X 
X /*
- * setup_smp()
- *
- * called from arch/alpha/kernel/setup.c:setup_arch() when __SMP__ defined
+ * A secondary console wants to send a message.  Receive it.
X  */
-void __init
-setup_smp(void)
-{
-	struct percpu_struct *cpubase, *cpu;
-	int i;
-	  
-	boot_cpu_id = hard_smp_processor_id();
-	if (boot_cpu_id != 0) {
-		printk("setup_smp: boot_cpu_id != 0 (%d).\n", boot_cpu_id);
-	}
-
-	if (hwrpb->nr_processors > 1) {
-
-		DBGS(("setup_smp: nr_processors %ld\n",
-		      hwrpb->nr_processors));
-
-		cpubase = (struct percpu_struct *)
-			((char*)hwrpb + hwrpb->processor_offset);
-		boot_cpu_palrev = cpubase->pal_revision;
-
-		for (i = 0; i < hwrpb->nr_processors; i++ ) {
-			cpu = (struct percpu_struct *)
-				((char *)cpubase + i*hwrpb->processor_size);
-			if ((cpu->flags & 0x1cc) == 0x1cc) {
-				smp_num_probed++;
-				/* assume here that "whami" == index */
-				cpu_present_map |= (1 << i);
-				if (i != boot_cpu_id)
-				  cpu->pal_revision = boot_cpu_palrev;
-			}
-
-			DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n",
-			      i, cpu->flags, cpu->type));
-			DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n",
-			      i, cpu->pal_revision));
-		}
-	} else {
-		smp_num_probed = 1;
-		cpu_present_map = (1 << boot_cpu_id);
-	}
-	printk("setup_smp: %d CPUs probed, cpu_present_map 0x%x,"
-	       " boot_cpu_id %d\n",
-	       smp_num_probed, cpu_present_map, boot_cpu_id);
-}
-
X static void
-secondary_console_message(void)
+recv_secondary_console_msg(void)
X {
X 	int mycpu, i, cnt;
X 	unsigned long txrdy = hwrpb->txrdy;
X 	char *cp1, *cp2, buf[80];
X 	struct percpu_struct *cpu;
X 
-	DBGS(("secondary_console_message: TXRDY 0x%lx.\n", txrdy));
+	DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy));
X 
X 	mycpu = hard_smp_processor_id();
X 
@@ -637,7 +285,7 @@
X 		if (!(txrdy & (1L << i)))
X 			continue;
X 
-		DBGS(("secondary_console_message: "
+		DBGS(("recv_secondary_console_msg: "
X 		      "TXRDY contains CPU %d.\n", i));
X 
X 		cpu = (struct percpu_struct *)
@@ -645,9 +293,9 @@
X 		   + hwrpb->processor_offset
X 		   + i * hwrpb->processor_size);
X 
- 		printk("secondary_console_message: on %d from %d"
-		       " HALT_REASON 0x%lx FLAGS 0x%lx\n",
-		       mycpu, i, cpu->halt_reason, cpu->flags);
+ 		DBGS(("recv_secondary_console_msg: on %d from %d"
+		      " HALT_REASON 0x%lx FLAGS 0x%lx\n",
+		      mycpu, i, cpu->halt_reason, cpu->flags));
X 
X 		cnt = cpu->ipc_buffer[0] >> 32;
X 		if (cnt <= 0 || cnt >= 80)
@@ -664,85 +312,347 @@
X 			}
X 		}
X 
-		printk("secondary_console_message: on %d message is '%s'\n",
-		       mycpu, buf);
+		printk(KERN_INFO "recv_secondary_console_msg: on %d "
+		       "message is '%s'\n", mycpu, buf);
X 	}
X 
X 	hwrpb->txrdy = 0;
X }
X 
-enum ipi_message_type {
-	IPI_TLB_ALL,
-	IPI_TLB_MM,
-	IPI_TLB_PAGE,
-	IPI_RESCHEDULE,
-	IPI_CPU_STOP
-};
-
-void
-handle_ipi(struct pt_regs *regs)
+/*
+ * Convince the console to have a secondary cpu begin execution.
+ */
+static int __init
+secondary_cpu_start(int cpuid, struct task_struct *idle)
X {
-	int this_cpu = smp_processor_id();
-	volatile int * pending_ipis = &ipi_bits[this_cpu];
-	unsigned long ops;
+	struct percpu_struct *cpu;
+	struct pcb_struct *hwpcb;
+	long timeout;
+	  
+	cpu = (struct percpu_struct *)
+		((char*)hwrpb
+		 + hwrpb->processor_offset
+		 + cpuid * hwrpb->processor_size);
+	hwpcb = (struct pcb_struct *) cpu->hwpcb;
X 
-	DBGS(("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n",
-	      this_cpu, *pending_ipis, regs->pc));
+	/* Initialize the CPU's HWPCB to something just good enough for
+	   us to get started.  Immediately after starting, we'll swpctx
+	   to the target idle task's tss.  Reuse the stack in the mean
+	   time.  Precalculate the target PCBB.  */
+	hwpcb->ksp = (unsigned long) idle + sizeof(union task_union) - 16;
+	hwpcb->usp = 0;
+	hwpcb->ptbr = idle->tss.ptbr;
+	hwpcb->pcc = 0;
+	hwpcb->asn = 0;
+	hwpcb->unique = virt_to_phys(&idle->tss);
+	hwpcb->flags = idle->tss.pal_flags;
+	hwpcb->res1 = hwpcb->res2 = 0;
X 
-	mb();	/* Order interrupt and bit testing. */
-	while ((ops = xchg(pending_ipis, 0)) != 0) {
-	  mb();	/* Order bit clearing and data access. */
-	  do {
-		unsigned long which;
+	DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
+	      hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique));
+	DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
+	      cpuid, idle->state, idle->tss.pal_flags));
X 
-		which = ops & -ops;
-		ops &= ~which;
-		which = ffz(~which);
+	/* Setup HWRPB fields that SRM uses to activate secondary CPU */
+	hwrpb->CPU_restart = __smp_callin;
+	hwrpb->CPU_restart_data = (unsigned long) __smp_callin;
X 
-		if (which < IPI_RESCHEDULE) {
-			if (which == IPI_TLB_ALL)
-				tbia();
-			else if (which == IPI_TLB_MM) {
-				struct mm_struct * mm;
-				mm = ipi_msg_flush_tb.p.flush_mm;
-				if (mm == current->mm)
-					flush_tlb_current(mm);
-			}
-			else /* IPI_TLB_PAGE */ {
-				struct vm_area_struct * vma;
-				struct mm_struct * mm;
-				unsigned long addr;
-
-				vma = ipi_msg_flush_tb.p.flush_vma;
-				mm = vma->vm_mm;
-				addr = ipi_msg_flush_tb.flush_addr;
+	/* Recalculate and update the HWRPB checksum */
+	hwrpb_update_checksum(hwrpb);
+
+	/*
+	 * Send a "start" command to the specified processor.
+	 */
X 
-				if (mm == current->mm)
-					flush_tlb_current_page(mm, vma, addr);
+	/* SRM III 3.4.1.3 */
+	cpu->flags |= 0x22;	/* turn on Context Valid and Restart Capable */
+	cpu->flags &= ~1;	/* turn off Bootstrap In Progress */
+	wmb();
+
+	send_secondary_console_msg("START\r\n", cpuid);
+
+	/* Wait 1 second for an ACK from the console.  Note that jiffies 
+	   aren't ticking yet.  */
+	for (timeout = 100000; timeout > 0; timeout--) {
+		if (cpu->flags & 1)
+			goto started;
+		udelay(10);
+		barrier();
+	}
+	printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid);
+	return -1;
+
+started:
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 02'
echo 'File patch-2.2.10 is continued in part 03'
echo 03 > _shar_seq_.tmp
exit 0
#!/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 22 - 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.10 ==============
if test -f 'patch-2.2.10' -a X"$1" != X"-c"; then
        echo 'x - skipping patch-2.2.10 (File already exists)'
        rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.10 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.10' &&
diff -u --recursive --new-file v2.2.9/linux/CREDITS linux/CREDITS
--- v2.2.9/linux/CREDITS	Tue May 11 13:10:26 1999
+++ linux/CREDITS	Wed Jun  9 22:23:01 1999
@@ -611,6 +611,13 @@
X S: Oak Park, Illinois 60302
X S: USA
X 
+N: Daniel J. Frasnelli
+E: dfra...@alphalinux.org   
+W: http://www.alphalinux.org/
+P: 1024/3EF87611 B9 F1 44 50 D3 E8 C2 80  DA E5 55 AA 56 7C 42 DA
+D: DEC Alpha hacker
+D: Miscellaneous bug squisher
+
X N: Jim Freeman
X E: jf...@sovereign.org
X W: http://www.sovereign.org/
@@ -656,7 +663,7 @@
X E: rgo...@atnf.csiro.au
X D: parent process death signal to children
X D: prctl() syscall
-D: /proc/mtrr support to manipulate MTRRs on Pentium Pro's
+D: /proc/mtrr support to manipulate MTRRs on Intel P6 family
X S: CSIRO Australia Telescope National Facility
X S: P.O. Box 76, Epping
X S: New South Wales, 2121
@@ -754,6 +761,13 @@
X S: London SE16 1GD
X S: United Kingdom
X 
+N: Bart Hartgers
+E: ba...@etpmod.phys.tue.nl
+D: MTRR emulation with Centaur MCRs
+S: Gen Stedmanstraat 212
+S: 5623 HZ Eindhoven
+S: The Netherlands
+
X N: Kai Harrekilde-Petersen
X E: k...@dolphinics.no
X D: Original author of the ftape-HOWTO, i82078 fdc detection code.
@@ -801,7 +815,7 @@
X S: Germany
X 
X N: Michael Hipp
-E: mh...@student.uni-tuebingen.de
+E: hi...@informatik.uni-tuebingen.de
X D: drivers for the racal ni5210 & ni6510 Ethernet-boards
X S: Talstr. 1
X S: D - 72072 Tuebingen
diff -u --recursive --new-file v2.2.9/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.9/linux/Documentation/Configure.help	Tue May 11 13:10:26 1999
+++ linux/Documentation/Configure.help	Sun Jun 13 19:54:06 1999
@@ -3749,34 +3749,49 @@
X   say M here and read Documentation/modules.txt. The module will be
X   called aic7xxx.o.
X 
-Override driver defaults for commands per LUN
-CONFIG_OVERRIDE_CMDS
-  Say Y here if you want to override the default maximum number of
-  commands that a single device on the aic7xxx controller is allowed
-  to have active at one time. This option only affects tagged queueing
-  capable devices. The driver uses a value of 24 by default.
-  If you say Y here, you can adjust the number of commands per LUN
-  with the following configuration option.
+Enable or Disable Tagged Command Queueing by default
+CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+  This option causes the aic7xxx driver to attempt to use tagged command
+  queueing on any devices that claim to support it.  If this is set to yes,
+  you can still turn off TCQ on troublesome devices with the use of the
+  tag_info boot parameter.  See /usr/src/linux/drivers/scsi/README.aic7xxx
+  for more information on that and other aic7xxx setup commands.  If this
+  option is turned off, you may still enable TCQ on known good devices by
+  use of the tag_info boot parameter.
X   
-  If unsure, say N.
-
-Maximum number of commands per LUN
-CONFIG_AIC7XXX_CMDS_PER_LUN
-  Specify the maximum number of commands you would like to allocate
-  per LUN (a LUN is a Logical Unit Number -- some physical SCSI
-  devices, e.g. CD jukeboxes, act logically as several separate units,
-  each of which gets its own number).
+  If you are unsure about your devices then it is safest to say N here.
+  
+  However, TCQ can increase performance on some hard drives by as much
+  as 50% or more, so I would recommend that if you say N here, that you
+  at least read the README.aic7xxx file so you will know how to enable
+  this option manually should your drives prove to be safe in regards
+  to TCQ.
+
+  Conversely, certain drives are known to lock up or cause bus resets when
+  TCQ is enabled on them.  If you have a Western Digital Enterprise SCSI
+  drive for instance, then don't even bother to enable TCQ on it as the
+  drive will become unreliable, and it will actually reduce performance.
+
+Default number of TCQ commands per device
+CONFIG_AIC7XXX_CMDS_PER_DEVICE
+  Specify the number of commands you would like to allocate per SCSI
+  device when Tagged Command Queueing (TCQ) is enabled on that device.
X 
-  Reasonable figures are in the range of 14 to 32 commands per device,
+  Reasonable figures are in the range of 8 to 24 commands per device,
X   but depending on hardware could be increased or decreased from that
X   figure. If the number is too high for any particular device, the
X   driver will automatically compensate usually after only 10 minutes
-  of uptime and will issue a message to alert you to the fact that the
-  number of commands for that device has been reduced. It will not
-  hinder performance if some of your devices eventually have their
-  commands per LUN reduced, but is a waste of memory if all of your
-  devices end up reducing this number down to a more reasonable
-  figure. Default: 24
+  of uptime. It will not hinder performance if some of your devices
+  eventually have their command depth reduced, but is a waste of memory
+  if all of your devices end up reducing this number down to a more
+  reasonable figure.
+  
+  NOTE: Certain very broken drives are known to lock up when given more
+  commands than they like to deal with.  Quantum Fireball drives are the
+  most common in this category.  For the Quantum Fireball drives I would
+  suggest no more than 8 commands per device.
+
+  Default: 8
X 
X Collect statistics to report in /proc
X CONFIG_AIC7XXX_PROC_STATS
@@ -5213,7 +5228,7 @@
X   section (except for CONFIG_IP_ROUTE_TOS and CONFIG_IP_ROUTE_FWMARK).
X   At the moment, few devices support fast switching (tulip is one of
X   them, modified 8390 can be found at
-  ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz).
+  ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz).
X 
X   If unsure, say N.
X 
@@ -5223,8 +5238,8 @@
X   during periods of extremal congestion. At the moment only a couple
X   of device drivers support it (really only one -- tulip, modified
X   8390 can be found at
-  ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz). Really, this
-  option is applicable to any machine attached to a fast enough
+  ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz).
+  Really, this option is applicable to any machine attached to a fast enough
X   network, and even a 10 Mb NIC is able to kill a not very slow box,
X   such as a 120MHz Pentium.
X 
@@ -6160,6 +6175,20 @@
X   module, say M here and read Documentation/modules.txt as well as
X   Documentation/networking/net-modules.txt.
X 
+SKnet MCA support
+CONFIG_SKMC
+  This are Micro Channel ethernet adapters.  You need to set CONFIG_MCA
+  to use this driver.  It's both available as an in-kernel driver and
+  as a module ( = code which can be inserted in and removed from the
+  running kernel whenever you want). If you want to compile it as a module,
+  say M here and read Documentation/modules.txt as well as
+  Documentation/networking/net-modules.txt. If you plan to use more than
+  one network card under linux, read the Multiple-Ethernet-mini-HOWTO,
+  available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.  Supported
+  cards are the SKnet Junior MC2 and the SKnet MC2(+).  Distinguishing
+  both cards is done automatically.  Note that using multiple boards
+  of different type hasn't been tested with this driver.
+
X EISA, VLB, PCI and on board controllers
X CONFIG_NET_EISA
X   This is another class of network cards which attach directly to the
@@ -6517,16 +6546,6 @@
X   under Linux, say Y here (you must also remember to enable the driver
X   for your HIPPI card below). Most people will say N here.
X   
-CERN HIPPI PCI adapter support
-CONFIG_CERN_HIPPI
-  Say Y here if this is your PCI HIPPI network card.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called cern_hippi.o. If you want to compile it as
-  a module, say M here and read Documentation/modules.txt. If unsure,
-  say N.
-
X Essential RoadRunner HIPPI PCI adapter support
X CONFIG_ROADRUNNER
X   Say Y here if this is your PCI HIPPI network card.
@@ -6627,9 +6646,6 @@
X   (PhotoCDs). There is a new driver (next question) which can do
X   this. If you want that one, say N here.
X 
-  If the driver doesn't work out of the box, you might want to have a
-  look at drivers/cdrom/mcd.h. 
-
X   If you say Y here, you should also say Y or M to "ISO 9660 CDROM
X   filesystem support" below, because that's the filesystem used on
X   CDROMs. 
@@ -7463,13 +7479,6 @@
X   want), say M here and read Documentation/modules.txt. The module
X   will be called smbfs.o. Most people say N, however.
X 
-SMB Win95 bug work-around
-CONFIG_SMB_WIN95
-  If you want to connect to a share exported by Windows 95, you should
-  say Y here. The Windows 95 server contains a bug that makes listing
-  directories unreliable. This option slows down the listing of
-  directories. This makes the Windows 95 server a bit more stable.
-
X Coda filesystem support
X CONFIG_CODA_FS
X   Coda is an advanced network filesystem, similar to NFS in that it
@@ -8684,6 +8693,9 @@
X 
X   The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
X   MTRRs. These are supported.
+  
+  The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
+  are supported.
X 
X   Saying Y here also fixes a problem with buggy SMP BIOSes which only
X   set the MTRRs for the boot CPU and not the secondary CPUs. This can
@@ -10759,6 +10771,30 @@
X   haven't changed the setting of jumper JP3 on the card. Removing the
X   jumper sets the card to 0x358.
X 
+ADS Cadet AM/FM Radio Tuner Card
+CONFIG_RADIO_CADET
+  Choose Y here if you have one of these AM/FM radio cards, and then fill
+  in the port address below.
+  
+  In order to control your radio card, you will need to use programs
+  that are compatible with the Video for Linux API. Information on 
+  this API and pointers to "v4l" programs may be found on the WWW at
+  http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
+  you need to have access to a machine on the Internet that has a 
+  program like lynx or netscape.
+
+  Further documentation on this driver can be found on the WWW at
+  http://linux.blackhawke.net/cadet.html. 
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called radio-cadet.o.
+
+ADS Cadet AM/FM Radio Tuner Card I/O Port
+CONFIG_RADIO_CADET_PORT
+  Enter the I/O address of the card here (most commonly 330). 
+
X SF16FMI Radio
X CONFIG_RADIO_SF16FMI
X   Choose Y here if you have one of these FM radio cards, and then fill
@@ -10941,6 +10977,15 @@
X   from the running kernel whenever you want). If you want to compile
X   it as a module, say M here and read Documentation/modules.txt.
X 
+PlanB Video-In for PowerMacs
+CONFIG_VIDEO_PLANB
+  PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
+  input hardware. If you want to experiment with this, say Y.
+  Otherwise, or if you don't understand a word, say N.
+  See http://www.cpu.lu/~mlan/planb.html for more info.
+
+  Saying M will compile this driver as a module (planb.o).
+
X #
X # ARM options
X #
@@ -11238,6 +11283,21 @@
X 
X   If unsure, say Y.
X 
+IrPORT IrDA Device Driver
+CONFIG_IRPORT_SIR
+  Say Y here if you want to build support for the IrPORT IrDA device
+  driver. If you want to compile it as a module, say M here and
+  read Documentation/modules.txt. IrPORT can be used instead of
+  IrTTY and sometimes this can be better. One example is if your
+  IrDA port does not have echo-canceling, which will work OK with
+  IrPORT since this driver is working in half-duplex mode only. You
+  don't need to use irattach with IrPORT, but you just insert it 
+  the same way as FIR drivers (insmod irport io=0x3e8 irq=11).
+  Notice that IrPORT is a SIR device driver which means that speed
+  is limited to 115200 bps.
+
+  If unsure, say Y.
+
X Winbond W83977AF IrDA Device Driver
X CONFIG_WINBOND_FIR
X   Say Y here if you want to build IrDA support for the Winbond
@@ -11261,6 +11321,13 @@
X   read Documentation/modules.txt. This chipset is used by the Toshiba
X   Tecra laptops.
X 
+Toshiba Type-O IR Port Device Driver
+CONFIG_TOSHIBA_FIR
+  Say Y here if you want to build support for the Toshiba Type-O IR
+  chipset. If you want to compile it as a module, say M here and
+  read Documentation/modules.txt. This chipset is used by the Toshiba
+  Libretto 100CT, and many more laptops.
+
X ESI JetEye PC Dongle
X CONFIG_ESI_DONGLE
X   Say Y here if you want to build support for the Extended Systems
@@ -11297,6 +11364,15 @@
X   normal 9-pin serial port connector, and can currently only be used
X   by IrTTY. To activate support for Greenwich dongles you will have to
X   insert "irattach -d girbil" in the /etc/irda/drivers script.
+
+Parallax Litelink dongle
+CONFIG_LITELINK_DONGLE
+  Say Y here if you want to build support for the Parallax Litelink
+  dongle. If you want to compile it as a module, say M here and read
+  Documentation/modules.txt. The Parallax dongle attaches to the
+  normal 9-pin serial port connector, and can currently only be used
+  by IrTTY. To activate support for Parallax dongles you will have to
+  insert "irattach -d litelink" in the /etc/irda/drivers script.
X 
X VME (Motorola and BVM) support
X CONFIG_VME
diff -u --recursive --new-file v2.2.9/linux/Documentation/isdn/CREDITS linux/Documentation/isdn/CREDITS
--- v2.2.9/linux/Documentation/isdn/CREDITS	Wed Apr  1 20:11:47 1998
+++ linux/Documentation/isdn/CREDITS	Wed Jun  2 11:29:27 1999
@@ -5,7 +5,7 @@
X Thomas Bogendörfer (tsbo...@bigbug.franken.de)
X   Tester, lots of bugfixes and hints.
X 
-Alan Cox (al...@cymru.net)
+Alan Cox (al...@redhat.com)
X   For help getting into standard-kernel.
X 
X Henner Eisen (e...@baty.hanse.de)
diff -u --recursive --new-file v2.2.9/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt
--- v2.2.9/linux/Documentation/kernel-parameters.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/kernel-parameters.txt	Mon Jun  7 16:13:07 1999
@@ -0,0 +1,336 @@
+June 1999		  Kernel Parameters			v2.2.9
+			  ~~~~~~~~~~~~~~~~~
+
+The following is a consolidated list of the kernel parameters as defined
+in the file init/main.c and sorted into English Dictionary order (defined
+as ignoring all punctuation and sorting digits before letters in a case
+insensitive manner), and with descriptions where known.
+
+The text in square brackets at the beginning of the description state the
+restrictions on the kernel for the said kernel parameter to be valid. The
+restrictions referred to are that the relevant option is valid if:
+
+    APIC	APIC support is enabled.
+    APM 	Automatic Power Management support is enabled.
+    AX25	Appropriate AX.25 support is enabled.
+    CD		Appropriate CD support is enabled.
+    EIDE	EIDE/ATAPI support is enabled.
+    FB		The frame buffer device is enabled.
+    HW		Appropriate hardware is enabled.
+    ISDN	Appropriate ISDN support is enabled.
+    JOY 	Appropriate joystick support is enabled.
+    LPT 	Printer support is enabled.
+    MCA 	MCA bus support is enabled.
+    MDA 	The MDA console is enabled.
+    MOUSE	Appropriate mouse support is enabled.
+    NET 	Appropriate network support is enabled.
+    NFS 	Appropriate NFS support is enabled.
+    PARIDE	The ParIDE subsystem is enabled.
+    PCI 	PCI bus support is enabled.
+    PCMCIA	The PCMCIA subsystem is enabled.
+    PNP 	Plug & Play support is enabled.
+    PS2 	Appropriate PS/2 support is enabled.
+    RAM 	RAMdisc support is enabled.
+    SCSI	Appropriate SCSI support is enabled.
+    SERIAL	Serial support is enabled.
+    SMP 	The kernel is an SMP kernel.
+    SOUND	Appropriate sound system support is enabled.
+    VGA 	The VGA console has been enabled.
+    VT		Virtual terminal support is enabled.
+    XT		IBM PC/XT MFM hard disk support is enabled.
+
+In addition, the following text indicates that the option:
+
+    BUGS=	Relates to possible processor bugs on the said processor.
+    KNL 	Is a kernel start-up parameter.
+
+Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
+a trailing = on the name of any parameter states that that parameter will
+be entered as an environment variable, whereas its absence indicates that
+it will appear as a kernel argument readable via /proc/cmdline by programs
+running once the system is up.
+
+    53c7xx=		[HW,SCSI]
+
+    adb_buttons=	[HW,MOUSE]
+
+    advansys=		[HW,SCSI]
+
+    aha152x=		[HW,SCSI]
+
+    aha1542=		[HW,SCSI]
+
+    aic7xxx=		[HW,SCSI]
+
+    AM53C974=		[HW,SCSI]
+
+    apm=		[APM] Automatic Power Management.
+
+    arcrimi=		[HW,NET]
+
+    atamouse=		[HW,MOUSE] Atari Mouse.
+
+    atascsi=		[HW,SCSI] Atari SCSI.
+
+    aztcd=		[HW,CD] Aztec CD driver.
+
+    baycom_par= 	[HW,AX25] BayCom Parallel Port AX.25 Modem.
+
+    baycom_ser_fdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Full
+			Duplex Mode.
+
+    baycom_ser_hdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Half
+			Duplex Mode.
+
+    bmouse=		[HW,MOUSE,PS2] Bus mouse.
+
+    BusLogic=		[HW,SCSI]
+
+    cdu31a=		[HW,CD]
+
+    cm206=		[HW,CD]
+
+    com20020=		[HW,NET]
+
+    com90io=		[HW,NET]
+
+    com90xx=		[HW,NET]
+
+    console=		
+
+    cyclades=		[HW,SERIAL] Cyclades multi-serial port adapter.
+
+    debug		[KNL] Enable kernel debugging.
+
+    decnet=		[HW,NET]
+
+    digi=		[HW,SERIAL]
+
+    digiepca=		[HW,SERIAL]
+
+    dmascc=		[HW,AX25,SERIAL] AX.25 Z80SCC driver with DMA
+			support available.
+
+    dmasound=		[HW,SOUND]
+
+    dtc3181e=		[HW,SCSI]
+
+    eata=		[HW,SCSI]
+
+    eda=		[HW,PS2]
+
+    edb=		[HW,PS2]
+
+    ether=		[HW,NET] Ethernet.
+
+    fd_mcs=		[HW,SCSI]
+
+    fdomain=		[HW,SCSI]
+
+    floppy=		[HW]
+
+    ftape=		[HW] Floppy Tape subsystem.
+
+    gdth=		[HW,SCSI]
+
+    gscd=		[HW,CD]
+
+    gvp11=		[HW,SCSI]
+
+    hd= 		[EIDE] IDE and EIDE hard drive subsystem.
+
+    hfmodem=		[HW,AX25]
+
+    HiSax=		[HW,ISDN]
+
+    hisax=		[HW,ISDN]
+
+    ibmmcascsi= 	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter.
+
+    icn=		[HW,ISDN]
+
+    in2000=		[HW,SCSI]
+
+    init=		[KNL]
+
+    ip= 		[PNP]
+
+    isp16=		[HW,CD]
+
+    js_14=		[HW,JOY]
+
+    js_am=		[HW,JOY]
+
+    js_an=		[HW,JOY]
+
+    js_as=		[HW.JOY]
+
+    js_console= 	[HW,JOY]
+
+    js_console2=	[HW,JOY]
+
+    js_console3=	[HW,JOY]
+
+    js_db9=		[HW,JOY]
+
+    js_db9_2=		[HW,JOY]
+
+    js_db9_3=		[HW,JOY]
+
+    js_tg=		[HW,JOY]
+
+    js_tg_2=		[HW,JOY]
+
+    js_tg_3=		[HW,JOY]
+
+    kbd-reset		[VT]
+
+    load_ramdisk=	[RAM]
+
+    lp= 		[LPT] Parallel Printer.
+
+    ltpc=		[HW]
+
+    mac5380=		[HW,SCSI]
+
+    maxcpus=		[SMP] States the maximum number of processors that
+			an SMP kernel should make use of.
+
+    max_scsi_luns=	[SCSI]
+
+    mca-pentium 	[BUGS=ix86]
+
+    mcd=		[HW,CD]
+
+    mcdx=		[HW,CD]
+
+    md= 		[HW]
+
+    mdacon=		[MDA]
+
+    msmouse=		[HW,MOUSE] Microsoft Mouse.
+
+    ncr5380=		[HW,SCSI]
+
+    ncr53c400=		[HW,SCSI]
+
+    ncr53c400a= 	[HW,SCSI]
+
+    ncr53c406a= 	[HW,SCSI]
+
+    ncr53c8xx=		[HW,SCSI]
+
+    nfsaddrs=		[NFS]
+
+    nfsroot=		[NFS]
+
+    no387		[BUGS=ix86] Tells the kernel to use the 387 maths
+			emulation library even if a 387 maths coprocessor
+			is present.
+
+    noapic		[SMP,APIC] Tells the kernel not to make use of any
+			APIC that may be present on the system.
+
+    no-halt		[BUGS=ix86]
+
+    noinitrd		[RAM] Tells the kernel not to load any configured
+			initial ramdisc.
+
+    no-scroll		[VGA]
+
+    nosmp		[SMP] Tells an SMP kernel to act as a UP kernel.
+
+    optcd=		[HW,CD]
+
+    panic=		
+
+    parport=		[HW,LP]
+
+    pas16=		[HW,SCSI]
+
+    pcbit=		[HW,ISDN]
+
+    pcd.		[PARIDE]
+
+    pci=		[PCI]
+
+    pd. 		[PARIDE]
+
+    pf. 		[PARIDE]
+
+    pg. 		[PARIDE]
+
+    pirq=		[SMP,APIC]
+
+    plip=		[LP,NET] Parallel port network link.
+
+    profile=
+
+    prompt_ramdisk=	[RAM] Whether to prompt for ramdisk before loading
+			its contents into memory.
+
+    pt. 		[PARIDE]
+
+    ramdisk=		[RAM]
+
+    ramdisk_size=	[RAM]
+
+    ramdisk_start=	[RAM]
+
+    reboot=		[BUGS=ix86]
+
+    reserve=
+
+    riscom8=		[HW,SERIAL]
+
+    ro			[KNL] Mount root device read-only on boot.
+
+    root=		
+
+    rw			[KNL] Mount root device read-write on boot.
+
+    sbpcd=		[HW,CD] Soundblaster CD adapter.
+
+    scsi_logging=	[SCSI]
+
+    sjcd=		[HW,CD]
+
+    sonycd535=		[HW,CD]
+
+    sound=		[SOUND]
+
+    soundmodem= 	[HW,AX25,SOUND] Sound cards used as AX.25 modems.
+
+    specialix=		[HW,SERIAL] Specialix multi-serial port adapter.
+
+    st= 		[HW]
+
+    st0x=		[HW,SCSI]
+
+    stram_swap= 	[HW]
+
+    sym53c416=		[HW,SCSI]
+
+    sym53c8xx=		[HW,SCSI]
+
+    t128=		[HW,SCSI]
+
+    tmc8xx=		[HW,SCSI]
+
+    tmscsim=		[HW,SCSI]
+
+    tp720=		[HW,PS2]
+
+    u14-34f=		[HW,SCSI]
+
+    video=		[FB]
+
+    wd33c93=		[HW,SCSI]
+
+    wd7000=		[HW,SCSI]
+
+    wdt=		[HW]
+
+    xd= 		[HW,XT]
+
+    xd_geo=		[HW,XT]
diff -u --recursive --new-file v2.2.9/linux/Documentation/networking/ethertap.txt linux/Documentation/networking/ethertap.txt
--- v2.2.9/linux/Documentation/networking/ethertap.txt	Sun Jun  7 11:16:26 1998
+++ linux/Documentation/networking/ethertap.txt	Mon Jun  7 16:13:07 1999
@@ -1,7 +1,7 @@
X Documentation on setup and use of EtherTap.
X 
X Contact Jay Schulist <Jay.Sc...@spacs.k12.wi.us> if you
-have questions or need futher assistance.
+have questions or need further assistance.
X 
X Introduction
X ============
@@ -49,11 +49,11 @@
X 
X         1.2.3.4 will be the router to the outside world
X         1.2.3.5 our box
-        2.0.0.1 our box (appletalk side)
-        2.0.0.* a pile of macintoys
+        2.0.0.1 our box (AppleTalk side)
+        2.0.0.* a pile of Macintoys
X 
X 
-[1.2.3.4]-------------1.2.3.5[Our Box]2.0.0.1---------> macs
+[1.2.3.4]-------------1.2.3.5[Our Box]2.0.0.1---------> Macs
X 
X The routing on our box would be
X 
diff -u --recursive --new-file v2.2.9/linux/Documentation/networking/ltpc.txt linux/Documentation/networking/ltpc.txt
--- v2.2.9/linux/Documentation/networking/ltpc.txt	Thu Nov 19 09:56:27 1998
+++ linux/Documentation/networking/ltpc.txt	Mon Jun  7 16:13:07 1999
@@ -65,7 +65,7 @@
X 
X Card Configuration:
X 
-The interrupts and so forth are configured via the dipswitch on the
+The interrupts and so forth are configured via the DIP switch on the
X board.  Set the switches so as not to conflict with other hardware.
X 
X        Interrupts -- set at most one.  If none are set, the driver uses
diff -u --recursive --new-file v2.2.9/linux/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt
--- v2.2.9/linux/Documentation/scsi-generic.txt	Wed Apr 28 11:37:29 1999
+++ linux/Documentation/scsi-generic.txt	Mon Jun  7 16:13:07 1999
@@ -1,34 +1,38 @@
-            Notes on Linux's SG driver version 2.1.30
+            Notes on Linux's SG driver version 2.1.34
X             -----------------------------------------
-                                                        990328
+                                                        990606
X 
X Introduction
X ============
+Sg is one of the four "high level" SCSI device drivers along with
+sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized
+(but lower level) than its siblings and tends to be used on SCSI devices
+that don't fit into the already serviced categories. Thus sg is used for
+scanners, cd writers and reading audio cds digitally amongst other things.
+
X These are notes on the Linux SCSI generic packet device driver (sg)
-describing version 2.1.30 . The original driver was written by Lawrence
-Foard and has remained in place with minimal changes since circa 1992.
+describing version 2.1.34 . The original driver was written by Lawrence
+Foard and remained in place with minimal changes since circa 1992.
X Version 2 of this driver remains backward compatible (binary and
X source **) with the original. It adds scatter gather, command queuing,
X per file descriptor sequencing, asynchronous notification and better
X error reporting.
X 
-Sg is one of the four "high level" SCSI device drivers along with
-sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized
-(but lower level) than its sibling and tends to be used on SCSI devices
-that don't fit into the already serviced categories. Thus sg is used for
-scanners, cd writers and reading audio cds amongst other things.
+This is an abridged version of the sg documentation that is targeted
+at the linux/Documentation directory. The full document can be found
+at http://www.torque.net/sg/p/scsi-generic_long.txt .
X 
-The interface and usage of the original sg driver has been documented
+The interface and usage of the original sg driver have been documented
X by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy
X of the document is version 1.5 dated 7th May 1996. It can found at
-ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/SCSI-Programming-HOWTO .
-Amongst other things it has a lot of tables from the SCSI-2 standard
-that are very useful for programming this interface.
+ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO-SCSI-Programming-HOWTO .
+A copy of this document can be found at:
+http://www.torque.net/sg/p/original/HOWTO-SCSI-Programming-HOWTO .
X 
X ** It is possible to write applications that perform differently
X depending on whether they are using the original or this version of
-the sg device driver. The author is not aware of any useful applications
-that have problems with version 2 (yet).
+the sg device driver. The author is not aware of any useful 
+pre-existing applications that have problems with version 2 (yet).
X 
X 
X Architecture
@@ -38,9 +42,11 @@
X the others are sd (for direct-access devices - disks), st (for tapes)
X and sr (for data cdroms). The other three devices are block devices.
X 
-The unifying layer of the SCSI sub-system in the so-called mid-level.
-Below that are all the drivers for the various adapters supported by
-Linux.
+The unifying layer of the SCSI sub-system is the so-called mid-level.
+Below that are the "low level" drivers which are the drivers for the
+various adapters supported by Linux. Also at this level are pseudo
+adapter drivers such as ide-scsi which converts the SCSI protocol to
+ATAPI (which are similar to one another) for use by IDE devices.
X 
X Since sg is a character device it supports the traditional Unix
X system calls of open(), close(), read(), write() and ioctl(). Two other
@@ -85,8 +91,9 @@
X     unsigned char sense_buffer[16];
X }; /* this structure is 36 bytes long */
X 
-The 'pack_len' is bizzare and ends up having the 'reply_len' put in it
-(perhaps it had a use at some stage). 
+The 'pack_len' is bizarre and ends up having the 'reply_len' put in it
+(perhaps it had a use at some stage). Even though it looks like an
+input variable, it is not read by sg internally (only written).
X 
X The 'reply_len' is the length of the data the corresponding read()
X will/should request (including the sg_header). 
@@ -95,14 +102,14 @@
X back to the corresponding read() so it can be used for sequencing by an
X application. 
X 
-The 'result' is also bizzare, turning certain types of host codes it 0 (no
+The 'result' is also bizarre, turning certain types of host codes to 0 (no
X error), EBUSY or EIO. With better error reporting now available, the
X 'result' is best ignored.
X 
-The 'twelve_byte' field overrides the internal SCSI command length "guessing"
+The 'twelve_byte' field overrides the internal SCSI command length detection
X algorithm for group 6 and 7 commands (ie when 1st byte >= 0xc0) and forces
-a command lenth of 12 bytes.
-The command length "guessing" algorithm is as follows:
+a command length of 12 bytes.
+The command length detection algorithm is as follows:
X Group:  0    1    2    3    4    5    6    7
X Length: 6   10   10   12   12   12   10   10
X 
@@ -115,6 +122,7 @@
X buffer should be at least 18 bytes long and arguably 32 bytes; unfortunately
X this is unlikely to happen in the 2.2.x series of kernels.
X 
+
X The new sg_header offered in this driver is:
X #define SG_MAX_SENSE 16
X struct sg_header
@@ -122,15 +130,17 @@
X     int pack_len;    /* [o] reply_len (ie useless) ignored as input */
X     int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
X     int pack_id;     /* [io] id number of packet (use ints >= 0) */
-    int result;      /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */
+    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
X     unsigned int twelve_byte:1;
X         /* [i] Force 12 byte command length for group 6 & 7 commands  */
X     unsigned int target_status:5;   /* [o] scsi status from target */
X     unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
X     unsigned int driver_status:8;   /* [o] driver status+suggestion */
X     unsigned int other_flags:10;    /* unused */
-    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] when target_status is
-               CHECK_CONDITION or COMMAND_TERMINATED this is output. */
+    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
+           when target_status is CHECK_CONDITION or 
+           when target_status is COMMAND_TERMINATED or
+           when (driver_status & DRIVER_SENSE) is true. */
X };      /* This structure is 36 bytes long on i386 */
X 
X Firstly the new header is binary compatible with the original. This is
@@ -146,6 +156,9 @@
X the value of 'pack_id' available after a read() is the value given to that
X variable in the prior, corresponding write().
X 
+The SCSI command length can now be given directly using the SG_NEXT_CMD_LEN
+ioctl().
+
X The 'target_status' field is always output and is the (masked and shifted
X 1 bit right) SCSI status code from the target device. The allowable
X values are (found in <scsi/scsi.h>):
@@ -162,28 +175,28 @@
X When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the
X 'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE)
X is true then the 'sense_buffer' is also output (this seems to occur when
-the scsi ide emulation is used). When the 'sense_buffer' is output the 
+the ide-scsi emulation is used). When the 'sense_buffer' is output the 
X SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) .
X 
X The 'host_status' field is always output and has the following values
-whose "defines" are not visible outside the kernel (unfortunately):
+whose "defines" are not visible outside the kernel. A copy of these
+defines can be found in sg_err.h (see the utilities section):
X #define DID_OK          0x00 /* NO error                                */
X #define DID_NO_CONNECT  0x01 /* Couldn't connect before timeout period  */
X #define DID_BUS_BUSY    0x02 /* BUS stayed busy through time out period */
X #define DID_TIME_OUT    0x03 /* TIMED OUT for other reason              */
-#define DID_BAD_TARGET  0x04 /* BAD target.                             */
+#define DID_BAD_TARGET  0x04 /* BAD target, device not responding?      */
X #define DID_ABORT       0x05 /* Told to abort for some other reason     */
X #define DID_PARITY      0x06 /* Parity error                            */
-#define DID_ERROR       0x07 /* Internal error                          */
+#define DID_ERROR       0x07 /* Internal error [DMA underrun on aic7xxx]*/
X #define DID_RESET       0x08 /* Reset by somebody.                      */
X #define DID_BAD_INTR    0x09 /* Got an interrupt we weren't expecting.  */
X #define DID_PASSTHROUGH 0x0a /* Force command past mid-layer            */
-#define DID_SOFT_ERROR  0x0b /* The low level driver just wish a retry  */
+#define DID_SOFT_ERROR  0x0b /* The low level driver wants a retry      */
X 
X The 'driver_status' field is always output. When ('driver_status' &
-DRIVER_SENSE) is true the 'sense_buffer' is also output. The following
-values whose "defines" are not visible outside the kernel (unfortunately)
-can occur:
+DRIVER_SENSE) is true the 'sense_buffer' is also output. A copy of these
+defines can be found in sg_err.h (see the utilities section):
X #define DRIVER_OK           0x00 /* Typically no suggestion */
X #define DRIVER_BUSY         0x01
X #define DRIVER_SOFT         0x02
@@ -192,7 +205,7 @@
X #define DRIVER_INVALID      0x05
X #define DRIVER_TIMEOUT      0x06
X #define DRIVER_HARD         0x07
-#define DRIVER_SENSE        0x08
+#define DRIVER_SENSE        0x08 /* Implies sense_buffer output */
X /* above status 'or'ed with one of the following suggestions */
X #define SUGGEST_RETRY       0x10
X #define SUGGEST_ABORT       0x20
@@ -200,55 +213,8 @@
X #define SUGGEST_DIE         0x40
X #define SUGGEST_SENSE       0x80
X 
-'other_flags' still remains as a 10 bit field, so code that places 0 in it
-will still be happy. It is not used.
-
-
-memory
-======
-Memory is a scarce resource in any computer. Sg needs to reserve memory
-suitable for DMA roughly equal in size to the maximum of the write and
-read data buffers for each packet. This DMA memory is obtained at the time
-of a write() and released when the corresponding read() is called (although
-if memory is tight it may be using the buffer reserved by the open() ).
-
-Linux obtaining memory a challenge for several reasons. The memory pool
-that sg uses is in common with all other device drivers and all user
-processes. In this environment the only way to 99.9% guarantee a driver
-will have memory in Linux is to build it into the kernel (ie not as a
-module) and then reserve it on initialization before user processes get
-a chance. [Of course, another driver initialized before sg could take
-all available memory ...] Another problem is the biggest contiguous
-chunk of memory that can be obtained from the kernel is 32 * PAGE_SIZE
-(which is 128KBytes on i386). As memory gets "splintered" there is a good
-chance that buffers won't be available (my machine has 64 MBytes of RAM
-and has 3 available at the moment).
-
-The original sg driver used the following technique: grab a SG_BIG_BUFF
-sized buffer at driver initialization and use it for all requests greater
-than PAGE_SIZE (4096 bytes on i386). By default SG_BIG_BUFF is set to
-32 KBytes in the origianl driver but many applications suggest that the
-user increases this number. Linux limits the biggest single buffer of
-this type to 32 * PAGE_SIZE (128KBytes on i386). Unfortunately if the
-sg driver is a module then there is a high chance a contiguous block of
-that large size will not be available at module initialization.
-
-The author has found no "silver bullet" solution but uses multiple
-techniques hoping that at least one is able provide memory at the critical
-time. Listed below are some of these techniques:
-        - use scatter gather: then instead of one large buffer needing to
-          be found, multiple smaller buffer can be used
-        - use memory above the 16MByte level: the original driver limited
-          itself to obtaining memory below the 16MByte level (on the i386)
-          due to the shortcomings of DMA on ISA adapters. Yet more and more
-          people use PCI adapters that don't have this problem. So make
-          the decision based on the capabilities of the host adpater
-          associated with the current SCSI device
-        - reserve some memory at open() for emergencies but otherwise
-          fetch and release it on a per packet basis
-        - if the kernel is short of memory then dip into the SCSI DMA
-          pool (maintained by the mid-level driver) to a limited amount
-
+'other_flags' still remains as a 10 bit field (reduced from 31 bits), so
+code that places 0 in it will still be happy. It is not used.
X 
X 
X System Calls
@@ -257,16 +223,16 @@
X Unix operating system calls when applied to a SCSI generic device
X using this version of the device driver.
X 
-open
-----
+open(const char * filename, int flags)
+--------------------------------------
X The filename should be an 'sg' device such as
X /dev/sg[a-z]
X /dev/sg[0,1,2,...]
X or a symbolic link to one of these. [Devfs has its own sub-directory for
-sg devices.] It seems as though SCSI devices are allocated to sg minor
-numbers in the same order as they appear in 'cat /proc/scsi/scsi'.
-Sg is a "character" based Linux device driver. This means it has an
-open/close/read/write/ioctl type interface.
+sg devices with entries like: /dev/sg/c1b2t3u4 .] It seems as though SCSI
+devices are allocated to sg minor numbers in the same order as they appear
+in 'cat /proc/scsi/scsi'. Sg is a "character" based Linux device driver.
+This means it has an open/close/read/write/ioctl type interface.
X 
X Flags can be either O_RDONLY or O_RDWR or-ed with either
X O_EXCL          waits for other opens on sg device to be closed before
@@ -279,7 +245,7 @@
X The original version of sg did not allow the O_RDONLY (yielding a EACCES
X error). This version allows it for accessing ioctls (e.g. doing an sg
X device scan with the SG_GET_SCSI_ID ioctl) but write()s will not be
-allowed.
+allowed. These flags are found in <fcntl.h> .
X 
X By default, sequencing is per file descriptor in this version of sg. This
X means, for example that 2 processes can independently manipulate the same
@@ -290,32 +256,38 @@
X previous version of sg supported only per device sequencing and this can
X still be selected with the SG_SET_MERGE_FD,1 ioctl().
X 
-The driver will attempt to reserve SG_SCATTER_SZ bytes (32KBytes in the
-current sg.h) on open() for "emergency" situations. If this is unavailable
-it will halve its request and try again. It gives up if PAGE_SIZE bytes
-(4096 bytes on i386) cannot be obtained so no memory is reserved. In this
-case open() will still return successfully. The actual amount of memory
-reserved can be found with the SG_GET_RESERVED_SIZE ioctl().
+The driver will attempt to reserve SG_DEF_RESERVED_SIZE bytes (32KBytes in
+the current sg.h) on open(). The size of this reserved buffer can
+subsequently be modified with the SG_SET_RESERVED_SIZE ioctl(). In both
+cases these are requests subject to various dynamic constraints. The actual
+amount of memory obtained can be found by the SG_GET_RESERVED_SIZE ioctl().
+The reserved buffer will be used if:
+    -  it is not already in use (eg when command queuing is in use)
+    -  a write() does not call for a buffer size larger than the
+       reserved size.
X 
X Returns a file descriptor if >= 0 , otherwise -1 implies an error.
X 
X Error codes (value in 'errno' after -1 returned):
-ENODEV          sg not compiled into kernel or the kernel cannot find the
-                sg module (or it can't initialize itself (low memory??))
-ENXIO           either scsi sub-system is currently processing some error
-                (eg doing a device reset) or the sg driver/module removed
-                or corrupted
+EACCES          Either the user doesn't have appropriate permissions on 
+                'filename' or attempted to use both O_RDONLY and O_EXCL
X EBUSY           O_NONBLOCK set and some user of this sg device has O_EXCL
X                 set while someone is already using this device
X EINTR           while waiting for an "exclusive" lock to clear, a signal
X                 is received, just try again ...        
+ENODEV          sg not compiled into kernel or the kernel cannot find the
+                sg module (or it can't initialize itself (low memory??))
+ENOENT          given filename not found
X ENOMEM          An attempt to get memory to store this open's context
X                 failed (this was _not_ a request to reserve DMA memory)
-EACCES          An attempt to use both O_RDONLY and O_EXCL
+ENXIO           either there is no attached device corresponding to given
+                filename or scsi sub-system is currently processing some
+                error (eg doing a device reset) or the sg driver/module
+                removed or corrupted
X 
X 
-write
------
+write(int sg_fd, const void * buffer, size_t count)
+---------------------------------------------------
X Even though sg is a character-based device driver it sends and receives
X packets to/from the associated scsi device. Write() is used to send a
X packet containing 2 mandatory parts and 1 optional part. The mandatory
@@ -343,32 +315,33 @@
X Returns number of bytes written if > 0 , otherwise -1 implies an error.
X 
X Error codes (value in 'errno' after -1 returned):
-ENXIO           either scsi sub-system is currently processing some error
-                (eg doing a device reset) or the sg driver/module removed
-                or corrupted
X EACCES          opened with RD_ONLY flag
-EIO             incoming buffer too short. It should be at least (6 +
-                sizeof(struct sg_header))==42 bytes long
-EDOM            a) command queuing off: a packet is already queued
-                b) command queuing on: too many packets queued 
-                   (SG_MAX_QUEUE exceeded)
X EAGAIN          SCSI mid-level out of command blocks (rare), try again.
X                 This is more likely to happen when queuing commands,
X                 so wait a bit (eg usleep(10000) ) before trying again
+EDOM            a) command queuing off: a packet is already queued
+                b) command queuing on: too many packets queued 
+                   (SG_MAX_QUEUE exceeded)
+                c) SCSI command length given in SG_NEXT_CMD_LEN too long
+EFAULT          'buffer' for 'count' bytes is an invalid memory range
+EIO             incoming buffer too short. It should be at least (6 +
+                sizeof(struct sg_header))==42 bytes long
X ENOMEM          can't get memory for DMA. Take evasive action ...
-                (see section on memory)
+ENXIO           either scsi sub-system is currently processing some error
+                (eg doing a device reset) or the sg driver/module removed
+                or corrupted
X 
X 
-read
-----
+read(int sg_fd, void * buffer, size_t count)
+--------------------------------------------
X Read() is used to receive a packet containing 1 mandatory part and 1 
X optional part. The mandatory part is:
X   - a control block (an instance of struct sg_header)
X The optional part is:
X   - incoming data (eg if a SCSI read command was sent by earlier write() )
X The buffer given to a read() and its corresponding count should be
-sufficient to accommodate this packet to avoid truncation. Truncation has
-occurred if count < sg_header::replylen .
+sufficient to accommodate this packet to avoid truncation. Truncation occurs
+if count < sg_header::replylen .
X 
X By default, read() will return the oldest packet queued up. If the 
X SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to
@@ -377,7 +350,6 @@
X wait or yield EAGAIN. As a special case, -1 in sg_header::pack_id given
X to read() will match the oldest packet.
X 
-
X Returns number of bytes read if > 0 , otherwise -1 implies an error.
X Unfortunately the return value in the non-error case is simply the
X same as the count argument. It is not the actual number of bytes
@@ -385,25 +357,26 @@
X such an underrun indication.
X 
X Error codes (value in 'errno' after -1 returned):
-ENXIO           either scsi sub-system is currently processing some error
-                (eg doing a device reset) or the sg driver/module removed
-                or corrupted
X EAGAIN          either no waiting packet or requested packet is not
X                 available while O_NONBLOCK flag was set
+EFAULT          'buffer' for 'count' bytes is an invalid memory range
X EINTR           while waiting for a packet, a signal is received, just
X                 try again ...        
X EIO             if the 'count' given to read() is < sizeof(struct sg_header)
X                 and the 'result' element in sg_header is non-zero. Not a
X                 recommended error reporting technique
+ENXIO           either scsi sub-system is currently processing some error
+                (eg doing a device reset) or the sg driver/module removed
+                or corrupted
X 
X 
-close
------
+close(int sg_fd)
+----------------
X Preferably a close() should be done after all issued write()s have had
X their corresponding read() calls completed. Unfortunately this is not
X always possible. The semantics of close() in Unix are to return more
X or less immediately (ie not wait on any event) so the driver needs to
-arrange to an orderly cleanup of those packets that are still "in
+arrange for an orderly cleanup of those packets that are still "in
X flight".
X 
X A process that has an open file descriptor to an sg device may be aborted
@@ -411,22 +384,22 @@
X (which is called 'sg_release()' in the version 2 driver) to facilitate
X the cleanup mentioned above.
X 
-A problem persists in version 2.1.8 if the sg driver is a module and is
-removed while packets are still "in flight". Hopefully this will be soon
-fixed.
+A problem persists in version 2.1.34 if the sg driver is a module and is
+removed while packets are still "in flight".
X 
X Returns 0 if successful, otherwise -1 implies an error.
X 
X Error codes (value in 'errno' after -1 returned):
X ENXIO           sg driver/module removed or corrupted
X 
-ioctl (sg specific)
--------------------
+ioctl(int sg_fd, int command, ...)  [sg specific]
+-------------------------------------------------
X Ken Thompson (or perhaps some other Unix luminary) described ioctl() as 
X the "garbage bin of Unix". This driver compounds the situation by adding
-around 18 more commands. These commands either yield state information (10
-of them), change the driver's characteristics (8 of them) or allow direct
-communication with the common SCSI mid-level driver.
+more ...
+If a ioctl command is not recognized by sg (and the various lower levels
+that it may pass the command on to) then the error EINVAL occurs. If an
+invalid address is given (in the 3rd argument) then the error EFAULT occurs.
X 
X Those commands with an appended "+" are new in version 2.
X 
@@ -442,15 +415,38 @@
X SG_SET_TIMEOUT:
X Assumes 3rd argument points to an int containing the new timeout value
X for this file descriptor. The unit is a "jiffy". Packets that are
-already "in flight" will not be effected. The default value is set
-on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h).
+already "in flight" will not be affected. The default value is set
+on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). This default is
+currently 1 minute and may not be long enough for formats.
X 
X SG_EMULATED_HOST:
X Assumes 3rd argument points to an int and outputs a flag indicating
-whether the host (adapter) is connected to a real SCSI bus or is
+whether the host (adapter) is connected to a real SCSI bus or is an
X emulated one (eg ide-scsi device driver). A value of 1 means emulated
X while 0 is not.
X 
+SG_SET_TRANSFORM  W:
+Third argument is ignored. Only is meaningful when SG_EMULATED host has
+yielded 1 (ie the low-level is the ide-scsi device driver); otherwise
+an EINVAL error occurs. The default state is to _not_ transform SCSI
+commands to the corresponding ATAPI commands but pass them straight
+through as is. [Only certain classes of SCSI commands need to be
+transformed to their ATAPI equivalents.] Making this ioctl command causes
+transforms to occur thereafter. Subsequent calls to this ioctl command
+have no additional effect. Beware, this state will affect all devices
+(and hence all related sg file descriptors) associated with this ide-scsi
+"bus".
+The author of ide-scsi has pointed out that this is not the intended
+behaviour which is a 3rd argument of 0 to disable transforms and 1 to
+enable transforms. Note the 3rd argument is an 'int' not a 'int *'.
+Perhaps the intended behaviour will be implemented soon.
+
+SG_GET_TRANSFORM:
+Third argument is ignored. Only is meaningful when SG_EMULATED host has
+yielded 1 (ie the low-level is the ide-scsi device driver); otherwise
+an EINVAL error occurs. Returns 0 to indicate _not_ transforming SCSI
+to ATAPI commands (default). Returns 1 when it is transforming.
+
X SG_SET_FORCE_LOW_DMA +:
X Assumes 3rd argument points to an int containing 0 or 1. 0 (default)
X means sg decides whether to use memory above 16 Mbyte level (on i386)
@@ -459,10 +455,10 @@
X space. 
X If 1 is given then the host adapter is overridden and only memory below
X the 16MB level is used for DMA. A requirement for this should be
-extremely rare. If the "reserve" buffer allocated on open() is not in
+extremely rare. If the "reserved" buffer allocated on open() is not in
X use then it will be de-allocated and re-allocated under the 16MB level
X (and the latter operation could fail yielding ENOMEM).
-Only the current file descriptor is effected.
+Only the current file descriptor is affected.
X 
X SG_GET_LOW_DMA +:
X Assumes 3rd argument points to an int and places 0 or 1 in it. 0
@@ -472,11 +468,11 @@
X adapters setting has been overridden by SG_SET_FORCE_LOW_DMA,1 .
X 
X SG_GET_SCSI_ID +:
-Assumes 3rd argument is pointing to an object of type Sg_scsi_id and
-populates it. That structure contains ints for host_no, channel,
-scsi_id, lun and scsi_type. Most of this information is available from
-other sources (eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER)
-but tends to be awkward to collect.
+Assumes 3rd argument is pointing to an object of type Sg_scsi_id (see
+sg.h) and populates it. That structure contains ints for host_no, 
+channel, scsi_id, lun and scsi_type. Most of this information is 
+available from other sources (eg SCSI_IOCTL_GET_IDLUN and 
+SCSI_IOCTL_GET_BUS_NUMBER) but tends to be awkward to collect.
X 
X SG_SET_FORCE_PACK_ID +:
X Assumes 3rd argument is pointing to an int. 0 (default) instructs read()
@@ -486,9 +482,9 @@
X oldest packet matching that pack_id or wait until it arrives (or yield
X EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1
X given to read() in the mode will match the oldest packet.
-Only the current file descriptor is effected by this command.
+Only the current file descriptor is affected by this command.
X 
-SG_GET_LOW_DMA +:
+SG_GET_PACK_ID +:
X Assumes 3rd argument points to an int and places the pack_id of the
X oldest (written) packet in it. If no packet is waiting to be read then
X yields -1.
@@ -503,30 +499,33 @@
X the adapter does support scatter gather.
X 
X SG_SET_RESERVED_SIZE +W:
-This is not currently implemented. It is intended for reserving either a
-large buffer or scatter gather list that will be available until the
-current file descriptor is closed. The requested amount of memory may
-not be available so SG_GET_RESERVED_SIZE should be used after this call
-to see how much was reserved. (EBUSY error possible)
+Assumes 3rd argument is pointing to an int. That value will be used to
+request a new reserved buffer of that size. The previous reserved buffer
+is freed (if it is not in use; if it was in use -EBUSY is returned).
+A new reserved buffer is then allocated and its actual size can be found by
+calling the SG_GET_RESERVED_SIZE ioctl(). The reserved buffer is then used
+for DMA purposes by subsequent write() commands if it is not already in
+use and if the write() is not calling for a buffer size larger than that
+reserved. The reserved buffer may well be a series of kernel buffers if the
+adapter supports scatter-gather. Large buffers can be requested (eg 1 MB).
X 
X SG_GET_RESERVED_SIZE +:
X Assumes 3rd argument points to an int and places the size in bytes of
-the DMA buffer reserved on open() for emergencies. If this is 0 then it
-is probably not wise to attempt on operation like burning a CD on this
-file descriptor.
+the reserved buffer from open() or the most recent SG_SET_RESERVED_SIZE
+ioctl() call on this fd.  The result can be 0 if memory is very tight. In
+this case it may not be wise to attempt something like burning a CD on
+this file descriptor.
X 
X SG_SET_MERGE_FD +W:
X Assumes 3rd argument is pointing to an int. 0 (the default) causes all
X subsequent sequencing to be per file descriptor. 1 causes all subsequent
X sequencing to be per device. If this command tries to change the current
-state and the is one or more _other_ file descriptors using this sg
-device then an EBUSY error occurs. Also if this file descriptor was not
-open()ed with the O_RDWR flag then an EACCES error occurs.
-Per device sequencing was the original semantics and allowed, for example
-different processes to "share" the device, one perhaps write()ing with
-the other one read()ing. This command is supplied if anyone needs those
-semantics. Per file descriptor sequencing, perhaps with the usage of
-the O_EXCL flag, seems more sensible.
+state and there is one or more _other_ file descriptors using this sg
+device then an EBUSY error occurs. Per device sequencing was the original
+semantics and allowed, for example different processes to "share" the
+device, one perhaps write()ing with the other one read()ing. This command
+is supplied if anyone needs those semantics. Per file descriptor 
+sequencing, perhaps with the use of the O_EXCL flag, seems more sensible.
X 
X SG_GET_MERGE_FD +:
X Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
@@ -538,14 +537,42 @@
X SG_DEF_COMMAND_Q in sg.h) disables command queuing. Attempts to write()
X a packet while one is already queued will result in a EDOM error.
X 1 turns command queuing on.
-Changing the queuing state only effects write()s done after the change.
-Only the current file descriptor is effected by this command.
+Changing the queuing state only affects write()s done after the change.
+Only the current file descriptor is affected by this command.
X 
X SG_GET_COMMAND_Q +:
X Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
X that command queuing is off on this file descriptor. 1 implies command
X queuing is on.
X 
+SG_SET_UNDERRUN_FLAG +:
+Assumes 3rd argument is pointing to an int. 0 (current default, set by
+SG_DEF_UNDERRUN_FLAG in sg.h) requests underruns be ignored. 1 requests
+that underruns be flagged. [The only low level driver that acts on this 
+at the moment is the aic7xxx which yields a DID_ERROR error on underrun.]
+Only the current file descriptor is affected by this command (unless
+"per device" sequencing has been selected).
+
+SG_GET_UNDERRUN_FLAG +:
+Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
+that underruns are not being reported. 1 implies that underruns are being
+reported (see SG_SET_UNDERRUN_FLAG for more details).
+
+SG_NEXT_CMD_LEN +:
+Assumes 3rd argument is pointing to an int. The value of the int (if > 0)
+will be used as the SCSI command length of the next SCSI command sent to
+a write() on this fd. After that write() the SCSI command length logic is
+reset to use automatic length detection (ie depending on SCSI command group
+and the 'twelve_byte' field). If the current SCSI command length maximum of
+12 is exceeded then the affected write() will yield an EDOM error.
+Giving this ioctl() a value of 0 will set automatic length detection for
+the next write(). N.B. Only the following write() on this fd is affected by
+this ioctl().
+
+SG_GET_VERSION_NUM +:
+Assumes 3rd argument points to an int. The version number is then placed
+in that int. A sg version such as 2.1.34 will yield "20134" from this ioctl.
+
X SG_SET_DEBUG +:
X Assumes 3rd argument is pointing to an int. 0 (default) turns debugging
X off. Values > 0 cause the SCSI sense buffer to be decoded and output
@@ -556,73 +583,53 @@
X the mid-level) then try 'echo "scsi dump 0" > /proc/scsi/scsi' and lots of
X debug will appear in your console/log.
X 
-ioctl (in common with sd, st + sr)
-----------------------------------
-The following ioctl()s can be called from any high-level scsi device
-driver (ie sd, st, sr + sg). Access permissions may differ a bit from
-one device to another, the access information given below is specific to
-the sg device driver.
-
-SCSI_IOCTL_GET_IDLUN:
-SCSI_IOCTL_GET_BUS_NUMBER:
-
-SCSI_IOCTL_SEND_COMMAND:  W
-If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto
-the SCSI mid-level driver for processing.
-Don't know much about this one but it looks pretty powerful and
-dangerous. Some comments says it is also deprecated.
-
-<any_command_not matching_above>:  W
-If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto
-the SCSI mid-level driver for processing.
-
X 
-poll
-----
+poll(struct pollfd * udfds, unsigned int nfds, int timeout_ms)
+--------------------------------------------------------------
X This is a native call in Linux 2.2 but most of its capabilities are available
X through the older select() call. Given a choice poll() should probably be
X used. Typically poll() is used when a sg scsi device is open()ed O_NONBLOCK
-for polling; or alternatively with asynchronous notification using the
-fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal.
+for polling; and optionally with asynchronous notification as well using
+the fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal.
X Only if something drastically is wrong (eg file handle gone stale) will
X POLLERR ever be set. POLLPRI, POLLHUP and POLLNVAL are never set.
X POLLIN is set when there is one or more packets waiting to be read.
-When POLLIN is set it implies that a read() will not block (or yield
+When POLLIN is set it implies that a read() will not block (nor yield
X EAGAIN in non-blocking mode) but return a packet immediately.
X POLLOUT (aka POLLWRNORM) is set when write() is able to accept a packet
-(ie will _not_ yield an EDOM error). The setting of POLLOUT is effected
+(ie will _not_ yield an EDOM error). The setting of POLLOUT is affected
X by the SG_SET_COMMAND_Q state: if the state is on then POLLOUT will remain
X set until the number of queued packets reaches SG_MAX_QUEUE, if the
X state is off then POLLOUT is only set when no packets are queued.
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 01'
echo 'File patch-2.2.10 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 07 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
X #define IO_EXTENT 8
X 
-/* static unsigned int io[]  = { 0x3e8, ~0, ~0, ~0 }; */
-/* static unsigned int irq[] = { 11, 0, 0, 0 }; */
+/* 
+ * Currently you'll need to set these values using insmod like this:
+ * insmod irport io=0x3e8 irq=11
+ */
+static unsigned int io[]  = { ~0, ~0, ~0, ~0 };
+static unsigned int irq[] = { 0, 0, 0, 0 };
+
+static unsigned int qos_mtt_bits = 0x03;
+
+static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static char *driver_name = "irport";
+
+static int irport_open(int i, unsigned int iobase, unsigned int irq);
+static int irport_close(struct irda_device *idev);
X 
X static void irport_write_wakeup(struct irda_device *idev);
X static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
X static void irport_receive(struct irda_device *idev);
X 
+static int  irport_net_init(struct device *dev);
+static int  irport_net_open(struct device *dev);
+static int  irport_net_close(struct device *dev);
+static int  irport_is_receiving(struct irda_device *idev);
+static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
+static int  irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
+
X __initfunc(int irport_init(void))
X {
-/* 	int i; */
+ 	int i;
X 
-/* 	for ( i=0; (io[i] < 2000) && (i < 4); i++) { */
-/* 		int ioaddr = io[i]; */
-/* 		if (check_region(ioaddr, IO_EXTENT)) */
-/* 			continue; */
-/* 		if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */
-/* 			return 0; */
-/* 	} */
-/* 	return -ENODEV; */
-	return 0;
+ 	for (i=0; (io[i] < 2000) && (i < 4); i++) {
+ 		int ioaddr = io[i];
+ 		if (check_region(ioaddr, IO_EXTENT))
+ 			continue;
+ 		if (irport_open(i, io[i], irq[i]) == 0)
+ 			return 0;
+ 	}
+	/* 
+	 * Maybe something failed, but we can still be usable for FIR drivers 
+	 */
+ 	return 0;
X }
X 
X /*
- * Function pc87108_cleanup ()
+ * Function irport_cleanup ()
X  *
- *    Close all configured chips
+ *    Close all configured ports
X  *
X  */
X #ifdef MODULE
X static void irport_cleanup(void)
X {
-/* 	int i; */
+ 	int i;
X 
X         DEBUG( 4, __FUNCTION__ "()\n");
X 
-	/* for ( i=0; i < 4; i++) { */
-/* 		if ( dev_self[i]) */
-/* 			irport_close( &(dev_self[i]->idev)); */
-/* 	} */
+	for (i=0; i < 4; i++) {
+ 		if (dev_self[i])
+ 			irport_close(dev_self[i]);
+ 	}
X }
X #endif /* MODULE */
X 
-/*
- * Function irport_open (void)
- *
- *    Start IO port 
- *
- */
-int irport_open(int iobase)
+static int irport_open(int i, unsigned int iobase, unsigned int irq)
X {
-	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
+	struct irda_device *idev;
+	int ret;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+/* 	if (irport_probe(iobase, irq) == -1) */
+/* 		return -1; */
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL);
+	if (idev == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset(idev, 0, sizeof(struct irda_device));
+   
+	/* Need to store self somewhere */
+	dev_self[i] = idev;
+
+	/* Initialize IO */
+	idev->io.iobase2   = iobase;
+        idev->io.irq2      = irq;
+        idev->io.io_ext    = IO_EXTENT;
+        idev->io.fifo_size = 16;
+
+	idev->netdev.base_addr = iobase;
+	idev->netdev.irq = irq;
+
+	/* Lock the port that we need */
+	ret = check_region(idev->io.iobase2, idev->io.io_ext);
+	if (ret < 0) { 
+		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      idev->io.iobase2);
+		/* irport_cleanup(self->idev);  */
+		return -ENODEV;
+	}
+	request_region(idev->io.iobase2, idev->io.io_ext, idev->name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&idev->qos);
+	
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200;
+
+	idev->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&idev->qos);
+	
+	idev->flags = IFF_SIR|IFF_PIO;
+
+	/* Specify which buffer allocation policy we need */
+	idev->rx_buff.flags = GFP_KERNEL;
+	idev->tx_buff.flags = GFP_KERNEL;
+
+	idev->rx_buff.truesize = 4000; 
+	idev->tx_buff.truesize = 4000;
+	
+	/* Initialize callbacks */
+	idev->change_speed    = irport_change_speed;
+	idev->wait_until_sent = irport_wait_until_sent;
+        idev->is_receiving    = irport_is_receiving;
+	idev->set_dtr_rts     = irport_set_dtr_rts;
+	idev->raw_write       = irport_raw_write;
+
+	/* Override the network functions we need to use */
+	idev->netdev.init            = irport_net_init;
+	idev->netdev.hard_start_xmit = irport_hard_xmit;
+	idev->netdev.open            = irport_net_open;
+	idev->netdev.stop            = irport_net_close;
+
+	/* Open the IrDA device */
+	irda_device_open(idev, driver_name, NULL);
+	
+	return 0;
+}
+
+static int irport_close(struct irda_device *idev)
+{
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	/* Release the IO-port that this driver is using */
+	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+	      idev->io.iobase2);
+	release_region(idev->io.iobase2, idev->io.io_ext);
+
+	irda_device_close(idev);
+
+	kfree(idev);
+
+	return 0;
+}
+
+void irport_start(struct irda_device *idev, int iobase)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&idev->lock, flags);
+
+	irport_stop(idev, iobase);
X 
X 	/* Initialize UART */
X 	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
X 	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
X 	
X 	/* Turn on interrups */
-	outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER);
+	outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
X 
-	return 0;
+	spin_unlock_irqrestore(&idev->lock, flags);
X }
X 
-/*
- * Function irport_cleanup ()
- *
- *    Stop IO port
- *
- */
-void irport_close(int iobase) 
+void irport_stop(struct irda_device *idev, int iobase)
X {
-	DEBUG(4, __FUNCTION__ "()\n");
+	unsigned long flags;
+
+	spin_lock_irqsave(&idev->lock, flags);
X 
X 	/* Reset UART */
X 	outb(0, iobase+UART_MCR);
-
+	
X 	/* Turn off interrupts */
X 	outb(0, iobase+UART_IER);
+
+	spin_unlock_irqrestore(&idev->lock, flags);
+}
+
+/*
+ * Function irport_probe (void)
+ *
+ *    Start IO port 
+ *
+ */
+int irport_probe(int iobase)
+{
+	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
+	return 0;
X }
X 
X /*
X  * Function irport_change_speed (idev, speed)
X  *
- *    Set speed of port to specified baudrate
+ *    Set speed of IrDA port to specified baudrate
X  *
X  */
-void irport_change_speed( int iobase, int speed) 
+void irport_change_speed(struct irda_device *idev, int speed)
X {
+	unsigned long flags;
+	int iobase; 
X 	int fcr;    /* FIFO control reg */
X 	int lcr;    /* Line control reg */
X 	int divisor;
X 
-	DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+	DEBUG(0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase2;
+	
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
+	spin_lock_irqsave(&idev->lock, flags);
X 
X 	/* Turn off interrupts */
X 	outb(0, iobase+UART_IER); 
X 
X 	divisor = SPEED_MAX/speed;
X 	
-	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
+	fcr = UART_FCR_ENABLE_FIFO;
+
+	/* 
+	 * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
+	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
+	 * about this timeout since it will always be fast enough. 
+	 */
+	if (idev->io.baudrate < 38400)
+		fcr |= UART_FCR_TRIGGER_1;
+	else 
+		fcr |= UART_FCR_TRIGGER_14;
X         
X 	/* IrDA ports use 8N1 */
X 	lcr = UART_LCR_WLEN8;
@@ -173,8 +318,10 @@
X 	outb(lcr,		  iobase+UART_LCR); /* Set 8N1	*/
X 	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */
X 
-	/* Turn on receive interrups */
-	outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); 
+	/* Turn on interrups */
+	outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+
+	spin_unlock_irqrestore(&idev->lock, flags);
X }
X 
X /*
@@ -188,10 +335,13 @@
X {
X 	int actual = 0;
X 	int iobase;
+	int fcr;
X 
X 	ASSERT(idev != NULL, return;);
X 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 
+	DEBUG(4, __FUNCTION__ "()\n");
+
X 	/* Finished with frame?  */
X 	if (idev->tx_buff.len > 0)  {
X 		/* Write data left in transmit buffer */
@@ -211,9 +361,18 @@
X 		/* Schedule network layer, so we can get some more frames */
X 		mark_bh(NET_BH);
X 
-		outb(UART_FCR_ENABLE_FIFO | 
-		     UART_FCR_TRIGGER_14  |
-		     UART_FCR_CLEAR_RCVR, iobase+UART_FCR); /* Enable FIFO's */
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
+
+		if (idev->io.baudrate < 38400)
+			fcr |= UART_FCR_TRIGGER_1;
+		else 
+			fcr |= UART_FCR_TRIGGER_14;
+
+		/* 
+		 * Reset Rx FIFO to make sure that all reflected transmit data
+		 * will be discarded
+		 */
+		outb(fcr, iobase+UART_FCR);
X 
X 		/* Turn on receive interrupts */
X 		outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); 
@@ -223,7 +382,7 @@
X /*
X  * Function irport_write (driver)
X  *
- *    
+ *    Fill Tx FIFO with transmit data
X  *
X  */
X static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
@@ -232,21 +391,18 @@
X 
X 	/* Tx FIFO should be empty! */
X 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
X 		return -1;
X 	}
X         
X 	/* Fill FIFO with current frame */
-	while (( fifo_size-- > 0) && (actual < len)) {
+	while ((fifo_size-- > 0) && (actual < len)) {
X 		/* Transmit next byte */
-		outb( buf[actual], iobase+UART_TX);
+		outb(buf[actual], iobase+UART_TX);
X 
X 		actual++;
X 	}
X         
-	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	      fifo_size, actual, len);
-
X 	return actual;
X }
X 
@@ -260,11 +416,10 @@
X int irport_hard_xmit(struct sk_buff *skb, struct device *dev)
X {
X 	struct irda_device *idev;
+	unsigned long flags;
X 	int actual = 0;
X 	int iobase;
X 
-	DEBUG(5, __FUNCTION__ "(), dev=%p\n", dev);
-
X 	ASSERT(dev != NULL, return 0;);
X 	
X 	idev = (struct irda_device *) dev->priv;
@@ -275,8 +430,19 @@
X 	iobase = idev->io.iobase2;
X 
X 	/* Lock transmit buffer */
-	if (irda_lock((void *) &dev->tbusy) == FALSE)
-		return -EBUSY;
+	if (irda_lock((void *) &dev->tbusy) == FALSE) {
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 5)
+			return -EBUSY;
+
+		WARNING("%s: transmit timed out\n", dev->name);
+		irport_start(idev, iobase);
+		irport_change_speed(idev, idev->io.baudrate);
+
+		dev->trans_start = jiffies;
+	}
+
+	spin_lock_irqsave(&idev->lock, flags);
X 	
X 	/* Init tx buffer */
X 	idev->tx_buff.data = idev->tx_buff.head;
@@ -291,6 +457,8 @@
X 	/* Turn on transmit finished interrupt. Will fire immediately!  */
X 	outb(UART_IER_THRI, iobase+UART_IER); 
X 
+	spin_unlock_irqrestore(&idev->lock, flags);
+
X 	dev_kfree_skb(skb);
X 	
X 	return 0;
@@ -307,10 +475,7 @@
X 	int iobase;
X 	int boguscount = 0;
X 
-	if (!idev)
-		return;
-
-	DEBUG(4, __FUNCTION__ "()\n");
+	ASSERT(idev != NULL, return;);
X 
X 	iobase = idev->io.iobase2;
X 
@@ -342,27 +507,42 @@
X 	int boguscount = 0;
X 
X 	if (!idev) {
-		printk(KERN_WARNING __FUNCTION__ 
-		       "() irq %d for unknown device.\n", irq);
+		WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq);
X 		return;
X 	}
X 
+	spin_lock(&idev->lock);
+
X 	idev->netdev.interrupt = 1;
X 
X 	iobase = idev->io.iobase2;
X 
-	iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+	iir = inb(iobase+UART_IIR) & UART_IIR_ID;
X 	while (iir) {
X 		/* Clear interrupt */
X 		lsr = inb(iobase+UART_LSR);
X 
-		if ((iir & UART_IIR_THRI) && (lsr & UART_LSR_THRE)) {
-			/* Transmitter ready for data */
-			irport_write_wakeup(idev);
-		} else if ((iir & UART_IIR_RDI) && (lsr & UART_LSR_DR)) {
-	       		/* Receive interrupt */
-			irport_receive(idev);
-		}
+		DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+		      iir, lsr, iobase);
+
+		switch (iir) {
+		case UART_IIR_RLSI:
+			DEBUG(0, __FUNCTION__ "(), RLSI\n");
+			break;
+		case UART_IIR_RDI:
+			if (lsr & UART_LSR_DR)
+				/* Receive interrupt */
+				irport_receive(idev);
+			break;
+		case UART_IIR_THRI:
+			if (lsr & UART_LSR_THRE)
+				/* Transmitter ready for data */
+				irport_write_wakeup(idev);
+			break;
+		default:
+			DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
+			break;
+		} 
X 		
X 		/* Make sure we don't stay here to long */
X 		if (boguscount++ > 32)
@@ -371,10 +551,175 @@
X  	        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
X 	}
X 	idev->netdev.interrupt = 0;
+
+	spin_unlock(&idev->lock);
+}
+
+static int irport_net_init(struct device *dev)
+{
+	/* Set up to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function irport_net_open (dev)
+ *
+ *    
+ *
+ */
+static int irport_net_open(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+
+	ASSERT(dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+
+	iobase = idev->io.iobase2;
+
+	if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, 
+			(void *) idev))
+		return -EAGAIN;
+
+	irport_start(idev, iobase);
+
+	MOD_INC_USE_COUNT;
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* Change speed to make sure dongles follow us again */
+	if (idev->change_speed)
+		idev->change_speed(idev, 9600);
+
+	return 0;
+}
+
+/*
+ * Function irport_net_close (idev)
+ *
+ *    
+ *
+ */
+static int irport_net_close(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+
+	ASSERT(dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	iobase = idev->io.iobase2;
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	irport_stop(idev, iobase);
+
+	free_irq(idev->io.irq2, idev);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function irport_wait_until_sent (idev)
+ *
+ *    Delay exectution until finished transmitting
+ *
+ */
+void irport_wait_until_sent(struct irda_device *idev)
+{
+	int iobase;
+
+	iobase = idev->io.iobase2;
+
+	/* Wait until Tx FIFO is empty */
+	while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+		DEBUG(2, __FUNCTION__ "(), waiting!\n");
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(MSECS_TO_JIFFIES(60));
+	}
+}
+
+/*
+ * Function irport_is_receiving (idev)
+ *
+ *    Returns true is we are currently receiving data
+ *
+ */
+static int irport_is_receiving(struct irda_device *idev)
+{
+	return (idev->rx_buff.state != OUTSIDE_FRAME);
+}
+
+/*
+ * Function irtty_set_dtr_rts (tty, dtr, rts)
+ *
+ *    This function can be used by dongles etc. to set or reset the status
+ *    of the dtr and rts lines
+ */
+static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+{
+	int iobase;
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase2;
+
+	if (dtr)
+		dtr = UART_MCR_DTR;
+	if (rts)
+		rts = UART_MCR_RTS;
+
+	outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR);
+}
+
+static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len)
+{
+	int iobase;
+	int actual = 0;
+
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	iobase = idev->io.iobase2;
+
+	/* Tx FIFO should be empty! */
+	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		return -1;
+	}
+        
+	/* Fill FIFO with current frame */
+	while (actual < len) {
+		/* Transmit next byte */
+		outb(buf[actual], iobase+UART_TX);
+		actual++;
+	}
+
+	return actual;
X }
X 
X #ifdef MODULE
X 
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(irq, "1-4i");
+
+MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
+MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode");
+
X /*
X  * Function cleanup_module (void)
X  *
@@ -393,11 +738,7 @@
X  */
X int init_module(void)
X {
-	if (irport_init() < 0) {
-		cleanup_module();
-		return 1;
-	}
-	return(0);
+	return irport_init();
X }
X 
X #endif /* MODULE */
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.2.9/linux/drivers/net/irda/irtty.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/irda/irtty.c	Wed Jun  2 11:31:36 1999
@@ -6,12 +6,12 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Thu Apr 22 09:20:24 1999
+ * Modified at:   Mon May 10 15:45:50 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       slip.c by Laurence Culhane,   <l...@holmes.demon.co.uk>
X  *                          Fred N. van Kempen, <wal...@uwalt.nl.mugnet.org>
X  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -24,7 +24,6 @@
X  *     
X  ********************************************************************/    
X 
-#include <linux/config.h>
X #include <linux/module.h>
X #include <asm/uaccess.h>
X #include <linux/kernel.h>
@@ -38,19 +37,21 @@
X #include <net/irda/irlap.h>
X #include <net/irda/timer.h>
X #include <net/irda/irda_device.h>
-#include <linux/kmod.h>
X 
X static hashbin_t *irtty = NULL;
-static hashbin_t *dongles = NULL;
X 
X static struct tty_ldisc irda_ldisc;
X 
-static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int qos_mtt_bits = 0x03;      /* 5 ms or more */
+
+static int  irtty_hard_xmit(struct sk_buff *skb, struct device *dev);
X static void irtty_wait_until_sent(struct irda_device *driver);
-static int irtty_is_receiving(struct irda_device *idev);
-static int irtty_net_init(struct device *dev);
-static int irtty_net_open(struct device *dev);
-static int irtty_net_close(struct device *dev);
+static int  irtty_is_receiving(struct irda_device *idev);
+static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
+static int  irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
+static int  irtty_net_init(struct device *dev);
+static int  irtty_net_open(struct device *dev);
+static int  irtty_net_close(struct device *dev);
X 
X static int  irtty_open(struct tty_struct *tty);
X static void irtty_close(struct tty_struct *tty);
@@ -73,13 +74,6 @@
X 		return -ENOMEM;
X 	}
X 
-	dongles = hashbin_new(HB_LOCAL);
-	if (dongles == NULL) {
-		printk(KERN_WARNING 
-		       "IrDA: Can't allocate dongles hashbin!\n");
-		return -ENOMEM;
-	}
-
X 	/* Fill in our line protocol discipline, and register it */
X 	memset(&irda_ldisc, 0, sizeof( irda_ldisc));
X 
@@ -132,7 +126,6 @@
X 	 *  function to hashbin_destroy().
X 	 */
X 	hashbin_delete(irtty, NULL);
-	hashbin_delete(dongles, NULL);
X }
X #endif /* MODULE */
X 
@@ -201,7 +194,7 @@
X 	/* The only value we must override it the baudrate */
X 	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
X 		IR_115200;
-	self->idev.qos.min_turn_time.bits = 0x0f;
+	self->idev.qos.min_turn_time.bits = qos_mtt_bits;
X 	self->idev.flags = IFF_SIR | IFF_PIO;
X 	irda_qos_bits_to_value(&self->idev.qos);
X 
@@ -216,7 +209,8 @@
X 	/* Initialize callbacks */
X 	self->idev.change_speed    = irtty_change_speed;
X  	self->idev.is_receiving    = irtty_is_receiving;
-	/* self->idev.is_tbusy        = irtty_is_tbusy; */
+	self->idev.set_dtr_rts     = irtty_set_dtr_rts;
+	self->idev.raw_write       = irtty_raw_write;
X 	self->idev.wait_until_sent = irtty_wait_until_sent;
X 
X 	/* Override the network functions we need to use */
@@ -248,10 +242,6 @@
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRTTY_MAGIC, return;);
X 
-	/* We are not using any dongle anymore! */
-	if (self->dongle_q)
-		self->dongle_q->dongle->close(&self->idev);
-
X 	/* Remove driver */
X 	irda_device_close(&self->idev);
X 
@@ -359,68 +349,6 @@
X }
X 
X /*
- * Function irtty_init_dongle (self, type)
- *
- *    Initialize attached dongle. Warning, must be called with a process
- *    context!
- */
-static void irtty_init_dongle(struct irtty_cb *self, int type)
-{
-	struct dongle_q *node;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-
-#ifdef CONFIG_KMOD
-	/* Try to load the module needed */
-	switch( type) {
-	case ESI_DONGLE:
-		MESSAGE("IrDA: Trying to initialize ESI dongle!\n");
-		request_module("esi");
-		break;
-	case TEKRAM_DONGLE:
-		MESSAGE("IrDA: Trying to initialize Tekram dongle!\n");
-		request_module("tekram");
-		break;
-	case ACTISYS_DONGLE:     /* FALLTHROUGH */
-	case ACTISYS_PLUS_DONGLE:
-		MESSAGE("IrDA: Trying to initialize ACTiSYS dongle!\n");
-		request_module("actisys");
-		break;
-	case GIRBIL_DONGLE:
-		MESSAGE("IrDA: Trying to initialize GIrBIL dongle!\n");
-		request_module("girbil");
-		break;
-	default:
-		ERROR("Unknown dongle type!\n");
-		return;
-	}
-#endif /* CONFIG_KMOD */
-
-	node = hashbin_find(dongles, type, NULL);
-	if ( !node) {
-		ERROR("Unable to find requested dongle\n");
-		return;
-	}
-	self->dongle_q = node;
-
-	/* Use this change speed function instead of the default */
-	self->idev.change_speed = node->dongle->change_speed;
-
-	/*
-	 * Now initialize the dongle!
-	 */
-	node->dongle->open(&self->idev, type);
-	node->dongle->qos_init(&self->idev, &self->idev.qos);
-	
-	/* Reset dongle */
-	node->dongle->reset(&self->idev, 0);
-
-	/* Set to default baudrate */
-	node->dongle->change_speed(&self->idev, 9600);
-}
-
-/*
X  * Function irtty_ioctl (tty, file, cmd, arg)
X  *
X  *     The Swiss army knife of system calls :-)
@@ -452,7 +380,7 @@
X 		break;
X 	case IRTTY_IOCTDONGLE:
X 		/* Initialize dongle */
-		irtty_init_dongle(self, (int) arg);
+		irda_device_init_dongle(&self->idev, (int) arg);
X 		break;
X 	default:
X 		return -ENOIOCTLCMD;
@@ -645,54 +573,23 @@
X 	tty_wait_until_sent(self->tty, 0);
X }
X 
-int irtty_register_dongle(struct dongle *dongle)
-{
-	struct dongle_q *new;
-	
-	/* Check if this compressor has been registred before */
-	if ( hashbin_find ( dongles, dongle->type, NULL)) {
-		DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n");
-                return 0;
-        }
-	
-	/* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
-        if (new == NULL)
-                return -1;
-		
-	memset(new, 0, sizeof( struct dongle_q));
-        new->dongle = dongle;
-
-	/* Insert IrDA dongle into hashbin */
-	hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL);
-	
-        return 0;
-}
-
-void irtty_unregister_dongle(struct dongle *dongle)
-{
-	struct dongle_q *node;
-
-	node = hashbin_remove(dongles, dongle->type, NULL);
-	if (!node) {
-		ERROR(__FUNCTION__ "(), dongle not found!\n");
-		return;
-	}
-	kfree(node);
-}
-
-
X /*
X  * Function irtty_set_dtr_rts (tty, dtr, rts)
X  *
X  *    This function can be used by dongles etc. to set or reset the status
X  *    of the dtr and rts lines
X  */
-void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts)
+static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
X {
+	struct tty_struct *tty;
+	struct irtty_cb *self;
X 	mm_segment_t fs;
X 	int arg = 0;
X 
+	self = (struct irtty_cb *) idev->priv;
+
+	tty = self->tty;
+
X #ifdef TIOCM_OUT2 /* Not defined for ARM */
X 	arg = TIOCM_OUT2;
X #endif
@@ -718,6 +615,25 @@
X 	set_fs(fs);
X }
X 
+static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
+{
+	struct irtty_cb *self;
+	int actual = 0;
+
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	
+	self = (struct irtty_cb *) idev->priv;
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
+
+	if (self->tty->driver.write)
+		actual = self->tty->driver.write(self->tty, 0, buf, len);
+
+	return actual;
+}
+
X static int irtty_net_init(struct device *dev)
X {
X 	/* Set up to be a normal IrDA network device driver */
@@ -759,6 +675,8 @@
X 
X MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
X MODULE_DESCRIPTION("IrDA TTY device driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
X 
X /*
X  * Function init_module (void)
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.2.9/linux/drivers/net/irda/litelink.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/litelink.c	Mon Jun  7 16:19:59 1999
@@ -0,0 +1,206 @@
+/*********************************************************************
+ *                
+ * Filename:      litelink.c
+ * Version:       1.0
+ * Description:   Driver for the Parallax LiteLink dongle
+ * Status:        Stable
+ * Author:        Dag Brattli <da...@cs.uit.no>
+ * Created at:    Fri May  7 12:50:33 1999
+ * Modified at:   Wed May 19 07:25:15 1999
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/dongle.h>
+
+#define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
+#define MAX_DELAY 10000   /* 1 ms */
+
+static void litelink_open(struct irda_device *idev, int type);
+static void litelink_close(struct irda_device *dev);
+static void litelink_change_speed(struct irda_device *dev, int baudrate);
+static void litelink_reset(struct irda_device *dev);
+static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
+
+/* These are the baudrates supported */
+static int baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
+
+static struct dongle dongle = {
+	LITELINK_DONGLE,
+	litelink_open,
+	litelink_close,
+	litelink_reset,
+	litelink_change_speed,
+	litelink_init_qos,
+};
+
+__initfunc(int litelink_init(void))
+{
+	return irda_device_register_dongle(&dongle);
+}
+
+void litelink_cleanup(void)
+{
+	irda_device_unregister_dongle(&dongle);
+}
+
+static void litelink_open(struct irda_device *idev, int type)
+{
+	strcat(idev->description, " <-> litelink");
+
+        idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void litelink_close(struct irda_device *idev)
+{
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function litelink_change_speed (tty, baud)
+ *
+ *    Change speed of the Litelink dongle. To cycle through the available 
+ *    baud rates, pulse RTS low for a few ms.  
+ */
+static void litelink_change_speed(struct irda_device *idev, int baudrate)
+{
+        int i;
+	
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	/* Clear RTS to reset dongle */
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+
+	/* Go back to normal mode */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+	
+	/* Cycle through avaiable baudrates until we reach the correct one */
+	for (i=0; i<5 && baud_rates[i] != baudrate; i++) {
+
+		/* Set DTR, clear RTS */
+		irda_device_set_dtr_rts(idev, FALSE, TRUE);
+		
+		/* Sleep a minimum of 15 us */
+		udelay(MIN_DELAY);
+		
+		/* Set DTR, Set RTS */
+		irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		
+		/* Sleep a minimum of 15 us */
+		udelay(MIN_DELAY);
+        }
+}
+
+/*
+ * Function litelink_reset (dev)
+ *
+ *      Reset the Litelink type dongle. Warning, this function must only be
+ *      called with a process context!
+ *
+ */
+static void litelink_reset(struct irda_device *idev)
+{
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	/* Power on dongle */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+
+	/* Clear RTS to reset dongle */
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+
+	/* Go back to normal mode */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+
+	/* This dongles speed defaults to 115200 bps */
+	idev->qos.baud_rate.value = 115200;
+}
+
+/*
+ * Function litelink_init_qos (qos)
+ *
+ *    Initialize QoS capabilities
+ *
+ */
+static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos)
+{
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
+MODULE_DESCRIPTION("Parallax Litelink dongle driver");	
+		
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Litelink module
+ *
+ */
+int init_module(void)
+{
+	return litelink_init();
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Litelink module
+ *
+ */
+void cleanup_module(void)
+{
+	litelink_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.2.9/linux/drivers/net/irda/pc87108.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/irda/pc87108.c	Mon Jun  7 16:19:59 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Tue Apr 20 11:11:39 1999
+ * Modified at:   Mon May 24 15:19:21 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>
X  *     Copyright (c) 1998 Lichen Wang, <lw...@actisys.com>
X  *     Copyright (c) 1998 Actisys Corp., www.actisys.com
X  *     All Rights Reserved
@@ -67,11 +67,12 @@
X #define BROKEN_DONGLE_ID
X 
X static char *driver_name = "pc87108";
+static int qos_mtt_bits = 0x07;  /* 1 ms or more */
X 
X #define CHIP_IO_EXTENT 8
X 
X static unsigned int io[]  = { 0x2f8, ~0, ~0, ~0 };
-static unsigned int io2[] = { 0x150, 0, 0, 0};
+static unsigned int io2[] = { 0x150, 0, 0, 0 };
X static unsigned int irq[] = { 3, 0, 0, 0 };
X static unsigned int dma[] = { 0, 0, 0, 0 };
X 
@@ -97,28 +98,28 @@
X };
X 
X /* Some prototypes */
-static int  pc87108_open( int i, unsigned int iobase, unsigned int board_addr, 
-			  unsigned int irq, unsigned int dma);
+static int  pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
+			 unsigned int irq, unsigned int dma);
X #ifdef MODULE
-static int  pc87108_close( struct irda_device *idev);
+static int  pc87108_close(struct irda_device *idev);
X #endif /* MODULE */
-static int  pc87108_probe( int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive( struct irda_device *idev);
-static int  pc87108_dma_receive( struct irda_device *idev); 
+static int  pc87108_probe(int iobase, int board_addr, int irq, int dma);
+static void pc87108_pio_receive(struct irda_device *idev);
+static int  pc87108_dma_receive(struct irda_device *idev); 
X static int  pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
-static int  pc87108_hard_xmit( struct sk_buff *skb, struct device *dev);
-static int  pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write( struct irda_device *idev, int iobase);
-static void pc87108_change_speed( struct irda_device *idev, int baud);
+static int  pc87108_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void pc87108_dma_write(struct irda_device *idev, int iobase);
+static void pc87108_change_speed(struct irda_device *idev, int baud);
X static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void pc87108_wait_until_sent( struct irda_device *idev);
-static int  pc87108_is_receiving( struct irda_device *idev);
-static int  pc87108_read_dongle_id ( int iobase);
-static void pc87108_init_dongle_interface ( int iobase, int dongle_id);
-
-static int  pc87108_net_init( struct device *dev);
-static int  pc87108_net_open( struct device *dev);
-static int  pc87108_net_close( struct device *dev);
+static void pc87108_wait_until_sent(struct irda_device *idev);
+static int  pc87108_is_receiving(struct irda_device *idev);
+static int  pc87108_read_dongle_id (int iobase);
+static void pc87108_init_dongle_interface (int iobase, int dongle_id);
+
+static int  pc87108_net_init(struct device *dev);
+static int  pc87108_net_open(struct device *dev);
+static int  pc87108_net_close(struct device *dev);
X 
X /*
X  * Function pc87108_init ()
@@ -130,11 +131,11 @@
X {
X 	int i;
X 
-	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+	for (i=0; (io[i] < 2000) && (i < 4); i++) {
X 		int ioaddr = io[i];
X 		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
X 			continue;
-		if (pc87108_open( i, io[i], io2[i], irq[i], dma[i]) == 0)
+		if (pc87108_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
X 			return 0;
X 	}
X 	return -ENODEV;
@@ -166,29 +167,29 @@
X  *    Open driver instance
X  *
X  */
-static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, 
-			 unsigned int irq, unsigned int dma)
+static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
+			unsigned int irq, unsigned int dma)
X {
X 	struct pc87108 *self;
X 	struct irda_device *idev;
X 	int ret;
X 	int dongle_id;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
X 
-	if (( dongle_id = pc87108_probe( iobase, board_addr, irq, dma)) == -1)
+	if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
X 		return -1;
X 
X 	/*
X 	 *  Allocate new instance of the driver
X 	 */
-	self = kmalloc( sizeof(struct pc87108), GFP_KERNEL);
-	if ( self == NULL) {
-		printk( KERN_ERR "IrDA: Can't allocate memory for "
-			"IrDA control block!\n");
+	self = kmalloc(sizeof(struct pc87108), GFP_KERNEL);
+	if (self == NULL) {
+		printk(KERN_ERR "IrDA: Can't allocate memory for "
+		       "IrDA control block!\n");
X 		return -ENOMEM;
X 	}
-	memset( self, 0, sizeof(struct pc87108));
+	memset(self, 0, sizeof(struct pc87108));
X    
X 	/* Need to store self somewhere */
X 	dev_self[i] = self;
@@ -203,24 +204,24 @@
X         idev->io.fifo_size = 32;
X 
X 	/* Lock the port that we need */
-	ret = check_region( idev->io.iobase, idev->io.io_ext);
-	if ( ret < 0) { 
-		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		       idev->io.iobase);
+	ret = check_region(idev->io.iobase, idev->io.io_ext);
+	if (ret < 0) { 
+		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      idev->io.iobase);
X 		/* pc87108_cleanup( self->idev);  */
X 		return -ENODEV;
X 	}
-	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
X 
X 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies( &idev->qos);
+	irda_init_max_qos_capabilies(&idev->qos);
X 	
X 	/* The only value we must override it the baudrate */
X 	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
X 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
X 	
-	idev->qos.min_turn_time.bits = 0x07;
-	irda_qos_bits_to_value( &idev->qos);
+	idev->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&idev->qos);
X 	
X 	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
X 
@@ -244,10 +245,10 @@
X 	idev->netdev.stop            = pc87108_net_close;
X 
X 	idev->io.dongle_id = dongle_id;
-	pc87108_init_dongle_interface( iobase, dongle_id);
+	pc87108_init_dongle_interface(iobase, dongle_id);
X 
X 	/* Open the IrDA device */
-	irda_device_open( idev, driver_name, self);
+	irda_device_open(idev, driver_name, self);
X 	
X 	return 0;
X }
@@ -259,23 +260,26 @@
X  *    Close driver instance
X  *
X  */
-static int pc87108_close( struct irda_device *idev)
+static int pc87108_close(struct irda_device *idev)
X {
+	struct pc87108 *self;
X 	int iobase;
X 
X 	DEBUG( 4, __FUNCTION__ "()\n");
X 
-	ASSERT( idev != NULL, return -1;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
X 
X         iobase = idev->io.iobase;
+	self = (struct pc87108 *) idev->priv;
X 
X 	/* Release the PORT that this driver is using */
-	DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", 
-	       idev->io.iobase);
-	release_region( idev->io.iobase, idev->io.io_ext);
+	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
+	release_region(idev->io.iobase, idev->io.io_ext);
X 
-	irda_device_close( idev);
+	irda_device_close(idev);
+
+	kfree(self);
X 
X 	return 0;
X }
@@ -287,22 +291,22 @@
X  *    Returns non-negative on success.
X  *
X  */
-static int pc87108_probe( int iobase, int board_addr, int irq, int dma) 
+static int pc87108_probe(int iobase, int board_addr, int irq, int dma) 
X {
X 	int version;
X 	__u8 temp=0;
X 	int dongle_id;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
X 	/* Base Address and Interrupt Control Register BAIC */
X 	outb(0, board_addr);
-	switch ( iobase) {
-	case 0x3E8: outb( 0x14, board_addr+1); break;
-	case 0x2E8: outb( 0x15, board_addr+1); break;
-	case 0x3F8: outb( 0x16, board_addr+1); break;
-	case 0x2F8: outb( 0x17, board_addr+1); break;
-	default:    DEBUG(0, __FUNCTION__ "(), invalid base_address");
+	switch (iobase) {
+	case 0x3E8: outb(0x14, board_addr+1); break;
+	case 0x2E8: outb(0x15, board_addr+1); break;
+	case 0x3F8: outb(0x16, board_addr+1); break;
+	case 0x2F8: outb(0x17, board_addr+1); break;
+	default:    ERROR(__FUNCTION__ "(), invalid base_address");
X 	}
X 	
X 	/* Control Signal Routing Register CSRT */
@@ -314,74 +318,73 @@
X 	case 9:  temp = 0x05; break;
X 	case 11: temp = 0x06; break;
X 	case 15: temp = 0x07; break;
-	default: DEBUG( 0, __FUNCTION__ "(), invalid irq");
+	default: ERROR(__FUNCTION__ "(), invalid irq");
X 	}
-	outb( 1, board_addr);
-
+	outb(1, board_addr);
+	
X 	switch (dma) {	
-	case 0: outb( 0x08+temp, board_addr+1); break;
-	case 1: outb( 0x10+temp, board_addr+1); break;
-	case 3: outb( 0x18+temp, board_addr+1); break;
+	case 0: outb(0x08+temp, board_addr+1); break;
+	case 1: outb(0x10+temp, board_addr+1); break;
+	case 3: outb(0x18+temp, board_addr+1); break;
X 	default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
X 	}
X 
X 	/* Mode Control Register MCTL */
-	outb( 2, board_addr);
-	outb( 0x03, board_addr+1);
+	outb(2, board_addr);
+	outb(0x03, board_addr+1);
X 		
X 	/* read the Module ID */
-	switch_bank( iobase, BANK3);
-	version =  inb( iobase+MID);
+	switch_bank(iobase, BANK3);
+	version = inb(iobase+MID);
X 	
X 	/* should be 0x2? */
-	if (0x20 != (version & 0xf0))
-	{
-		DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
+	if (0x20 != (version & 0xf0)) {
+		ERROR(__FUNCTION__ "(), Wrong chip version %02x\n", version);
X 		return -1;
X 	}
X 	
X 	/* Switch to advanced mode */
X 	switch_bank( iobase, BANK2);
-	outb( ECR1_EXT_SL, iobase+ECR1);
-	switch_bank( iobase, BANK0);
+	outb(ECR1_EXT_SL, iobase+ECR1);
+	switch_bank(iobase, BANK0);
X 
-	dongle_id = pc87108_read_dongle_id( iobase);
-	DEBUG( 0, __FUNCTION__ "(), Found dongle: %s\n", 
-	       dongle_types[ dongle_id]);
+	dongle_id = pc87108_read_dongle_id(iobase);
+	DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", 
+	      dongle_types[ dongle_id]);
X 	
X 	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
-	switch_bank( iobase, BANK0);	
-	outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	switch_bank(iobase, BANK0);	
+	outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
X 	
X 	/* Set FIFO size to 32 */
-	switch_bank( iobase, BANK2);
-	outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
X 
X 	/* IRCR2: FEND_MD is set */
-	switch_bank( iobase, BANK5);
-	outb( 0x2a, iobase+4);
+	switch_bank(iobase, BANK5);
+	outb(0x2a, iobase+4);
X 
X 	/* Make sure that some defaults are OK */
-	switch_bank( iobase, BANK6);
-	outb( 0x20, iobase+0); /* Set 32 bits FIR CRC */
-	outb( 0x0a, iobase+1); /* Set MIR pulse width */
-	outb( 0x0d, iobase+2); /* Set SIR pulse width */
-	outb( 0x2a, iobase+4); /* Set beginning frag, and preamble length */
+	switch_bank(iobase, BANK6);
+	outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
+	outb(0x0a, iobase+1); /* Set MIR pulse width */
+	outb(0x0d, iobase+2); /* Set SIR pulse width */
+	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
X 
X 	/* Receiver frame length */
-	switch_bank( iobase, BANK4);
-	outb( 2048 & 0xff, iobase+6);
-	outb(( 2048 >> 8) & 0x1f, iobase+7);
+	switch_bank(iobase, BANK4);
+	outb(2048 & 0xff, iobase+6);
+	outb((2048 >> 8) & 0x1f, iobase+7);
X 
X 	/* Transmitter frame length */
-	outb( 2048 & 0xff, iobase+4);
-	outb(( 2048 >> 8) & 0x1f, iobase+5);
+	outb(2048 & 0xff, iobase+4);
+	outb((2048 >> 8) & 0x1f, iobase+5);
X 	
-	DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version);
+	DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
X 
X 	/* Enable receive interrupts */
-	switch_bank( iobase, BANK0);
-	outb( IER_RXHDL_IE, iobase+IER);
+	switch_bank(iobase, BANK0);
+	outb(IER_RXHDL_IE, iobase+IER);
X 
X 	return dongle_id;
X }
@@ -404,10 +407,10 @@
X 	bank = inb( iobase+BSR);
X 
X 	/* Select Bank 7 */
-	switch_bank( iobase, BANK7);
+	switch_bank(iobase, BANK7);
X 	
X 	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
-	outb( 0x00, iobase+7);
+	outb(0x00, iobase+7);
X 	
X 	/* ID0, 1, and 2 are pulled up/down very slowly */
X 	udelay(50);
@@ -416,16 +419,16 @@
X 	dongle_id = inb( iobase+4) & 0x0f;
X 
X #ifdef BROKEN_DONGLE_ID
-	if ( dongle_id == 0x0a)
+	if (dongle_id == 0x0a)
X 		dongle_id = 0x09;
X #endif
-
+	
X 	/* Go back to  bank 0 before returning */
-	switch_bank( iobase, BANK0);
+	switch_bank(iobase, BANK0);
X 
-	DEBUG( 0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
+	DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
X 
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
X 
X 	return dongle_id;
X }
@@ -438,7 +441,7 @@
X  *     power-on/reset. It also needs to be used whenever you suspect that
X  *     the dongle is changed. 
X  */
-static void pc87108_init_dongle_interface ( int iobase, int dongle_id)
+static void pc87108_init_dongle_interface (int iobase, int dongle_id)
X {
X 	int bank;
X 
@@ -805,7 +808,6 @@
X 	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
X 		  DMA_MODE_WRITE);
X 	
-	/* idev->media_busy = TRUE; */
X 	idev->io.direction = IO_XMIT;
X 	
X 	/* Choose transmit DMA channel  */ 
@@ -814,11 +816,11 @@
X 	      iobase+ECR1);
X 	
X 	/* Enable DMA */
- 	switch_bank( iobase, BANK0);	
-	outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+ 	switch_bank(iobase, BANK0);	
+	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
X 
X 	/* Restore bank register */
-	outb( bsr, iobase+BSR);
+	outb(bsr, iobase+BSR);
X }
X 
X /*
@@ -828,7 +830,7 @@
X  *    got transfered
X  *
X  */
-static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size)
+static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
X {
X 	int actual = 0;
X 	__u8 bank;
@@ -847,16 +849,16 @@
X 	}
X 
X 	/* Fill FIFO with current frame */
-	while (( fifo_size-- > 0) && (actual < len)) {
+	while ((fifo_size-- > 0) && (actual < len)) {
X 		/* Transmit next byte */
-		outb( buf[actual++], iobase+TXD);
+		outb(buf[actual++], iobase+TXD);
X 	}
X         
-	DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	       fifo_size, actual, len);
+	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+	      fifo_size, actual, len);
X 
X 	/* Restore bank */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
X 
X 	return actual;
X }
@@ -973,7 +975,7 @@
X  *
X  *    
X  */
-static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase)
+static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
X {
X 	struct sk_buff *skb;
X 	struct pc87108 *self;
@@ -988,8 +990,6 @@
X 	/* Save current bank */
X 	bank = inb( iobase+BSR);
X 	
-	iobase = idev->io.iobase;
-
X 	/* Read status FIFO */
X 	switch_bank(iobase, BANK5);
X 	while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
@@ -1003,18 +1003,18 @@
X 	}
X 	
X 	/* Try to process all entries in status FIFO */
-	switch_bank( iobase, BANK0);
-	while ( st_fifo->len) {
+	switch_bank(iobase, BANK0);
+	while (st_fifo->len) {
X       
X 		/* Get first entry */
-		status = st_fifo->entries[ st_fifo->head].status;
-		len    = st_fifo->entries[ st_fifo->head].len;
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
X 		st_fifo->head++;
X 		st_fifo->len--;
X 
X 		/* Check for errors */
-		if ( status & FRM_ST_ERR_MSK) {
-			if ( status & FRM_ST_LOST_FR) {
+		if (status & FRM_ST_ERR_MSK) {
+			if (status & FRM_ST_LOST_FR) {
X 				/* Add number of lost frames to stats */
X 				idev->stats.rx_errors += len;	
X 			} else {
@@ -1188,8 +1188,8 @@
X 	bank = inb( iobase+BSR);
X 	
X 	/* Status event, or end of frame detected in FIFO */
-	if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) {
-		if ( pc87108_dma_receive_complete( idev, iobase)) {
+	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+		if (pc87108_dma_receive_complete( idev, iobase)) {
X 
X 			/* Wait for next status FIFO interrupt */
X 			new_ier |= IER_SFIF_IE;
@@ -1459,6 +1459,14 @@
X }
X 
X #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
+MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
X 
X /*
X  * Function init_module (void)
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.2.9/linux/drivers/net/irda/smc-ircc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/smc-ircc.c	Mon Jun  7 16:19:59 1999
@@ -0,0 +1,969 @@
+/*********************************************************************
+ *                
+ * Filename:      smc-ircc.c
+ * Version:       0.1
+ * Description:   Driver for the SMC Infrared Communications Controller (SMC)
+ * Status:        Experimental.
+ * Author:        Thomas Davis (tad...@jps.net)
+ * Created at:    
+ * Modified at:   Wed May 19 15:30:08 1999
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     I, Thomas Davis, admit no liability nor provide warranty for any
+ *     of this software. This material is provided "AS-IS" and at no charge.
+ *
+ *     Applicable Models : Fujitsu Lifebook 635t
+ *			   Sony PCG-505TX (gets DMA wrong.)
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/smc-ircc.h>
+#include <net/irda/irport.h>
+
+static char *driver_name = "smc-ircc";
+
+#define CHIP_IO_EXTENT 8
+
+static unsigned int io[]  = { 0x2e8, 0x140, ~0, ~0 };
+static unsigned int io2[] = { 0x2f8, 0x3e8, 0, 0};
+
+static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+
+/* Some prototypes */
+static int  ircc_open( int i, unsigned int iobase, unsigned int board_addr);
+static int  ircc_close( struct irda_device *idev);
+static int  ircc_probe( int iobase, int board_addr);
+static int  ircc_dma_receive( struct irda_device *idev); 
+static int  ircc_dma_receive_complete(struct irda_device *idev, int iobase);
+static int  ircc_hard_xmit( struct sk_buff *skb, struct device *dev);
+static void ircc_dma_write( struct irda_device *idev, int iobase);
+static void ircc_change_speed( struct irda_device *idev, int baud);
+static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void ircc_wait_until_sent( struct irda_device *idev);
+static int  ircc_is_receiving( struct irda_device *idev);
+
+static int  ircc_net_init( struct device *dev);
+static int  ircc_net_open( struct device *dev);
+static int  ircc_net_close( struct device *dev);
+
+static int ircc_debug=3;
+static int ircc_irq=255;
+static int ircc_dma=255;
+
+static inline void register_bank(int port, int bank)
+{
+        outb(((inb(port+UART_MASTER) & 0xF0) | (bank & 0x07)),
+             port+UART_MASTER);
+}
+
+static inline unsigned int serial_in(int port, int offset)
+{
+        return inb(port+offset);
+}
+
+static inline void serial_out(int port, int offset, int value)
+{
+        outb(value, port+offset);
+}
+
+/*
+ * Function ircc_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+__initfunc(int ircc_init(void))
+{
+	int i;
+
+	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+		int ioaddr = io[i];
+		if (check_region(ioaddr, CHIP_IO_EXTENT))
+			continue;
+		if (ircc_open( i, io[i], io2[i]) == 0)
+			return 0;
+	}
+	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+
+	return -ENODEV;
+}
+
+/*
+ * Function ircc_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void ircc_cleanup(void)
+{
+	int i;
+
+	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+	for ( i=0; i < 4; i++) {
+		if ( dev_self[i])
+			ircc_close( &(dev_self[i]->idev));
+	}
+	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+}
+#endif /* MODULE */
+
+/*
+ * Function ircc_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+static int ircc_open( int i, unsigned int iobase, unsigned int iobase2)
+{
+	struct ircc_cb *self;
+	struct irda_device *idev;
+	int ret;
+	int config;
+
+	DEBUG( ircc_debug, __FUNCTION__ " -->\n");
+
+	if ((config = ircc_probe( iobase, iobase2)) == -1) {
+	        DEBUG(ircc_debug, 
+		      __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
+		return -1;
+	}
+	
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc( sizeof(struct ircc_cb), GFP_KERNEL);
+	if ( self == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset(self, 0, sizeof(struct ircc_cb));
+   
+	/* Need to store self somewhere */
+	dev_self[i] = self;
+
+	idev = &self->idev;
+
+	/* Initialize IO */
+	idev->io.iobase    = iobase;
+        idev->io.iobase2   = iobase2; /* Used by irport */
+        idev->io.irq       = config >> 4 & 0x0f;
+	if (ircc_irq < 255) {
+	        printk(KERN_INFO "smc: Overriding IRQ - chip says %d, using %d\n",
+		      idev->io.irq, ircc_irq);
+		idev->io.irq = ircc_irq;
+	}
+        idev->io.io_ext    = CHIP_IO_EXTENT;
+        idev->io.io_ext2   = 8;       /* Used by irport */
+        idev->io.dma       = config & 0x0f;
+	if (ircc_dma < 255) {
+	        printk(KERN_INFO "smc: Overriding DMA - chip says %d, using %d\n",
+		      idev->io.dma, ircc_dma);
+		idev->io.dma = ircc_dma;
+	}
+        idev->io.fifo_size = 16;
+
+	/* Lock the port that we need */
+	ret = check_region( idev->io.iobase, idev->io.io_ext);
+	if ( ret < 0) { 
+		DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+		       idev->io.iobase);
+		/* ircc_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	ret = check_region( idev->io.iobase2, idev->io.io_ext2);
+	if ( ret < 0) { 
+		DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+		       idev->io.iobase2);
+		/* ircc_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+        request_region( idev->io.iobase2, idev->io.io_ext2, idev->name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies( &idev->qos);
+	
+#if 1
+	/* The only value we must override it the baudrate */
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+#else
+	/* The only value we must override it the baudrate */
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200;
+#endif
+
+	idev->qos.min_turn_time.bits = 0x07;
+	irda_qos_bits_to_value( &idev->qos);
+
+	idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+	
+	/* Specify which buffer allocation policy we need */
+	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	idev->rx_buff.truesize = 4000; 
+	idev->tx_buff.truesize = 4000;
+	
+	/* Initialize callbacks */
+	idev->change_speed    = ircc_change_speed;
+	idev->wait_until_sent = ircc_wait_until_sent;
+	idev->is_receiving    = ircc_is_receiving;
+     
+	/* Override the network functions we need to use */
+	idev->netdev.init            = ircc_net_init;
+	idev->netdev.hard_start_xmit = ircc_hard_xmit;
+	idev->netdev.open            = ircc_net_open;
+	idev->netdev.stop            = ircc_net_close;
+
+	irport_start(idev, iobase2);
+
+	/* Open the IrDA device */
+	irda_device_open( idev, driver_name, self);
+	
+	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	return 0;
+}
+
+/*
+ * Function ircc_close (idev)
+ *
+ *    Close driver instance
+ *
+ */
+static int ircc_close( struct irda_device *idev)
+{
+	int iobase;
+
+	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+        iobase = idev->io.iobase;
+
+	irport_stop(idev, idev->io.iobase2);
+
+	register_bank(iobase, 0);
+	serial_out(iobase, UART_IER, 0);
+	serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+
+	register_bank(iobase, 1);
+
+        serial_out(iobase, UART_SCE_CFGA, 
+		   UART_CFGA_IRDA_SIR_A | UART_CFGA_TX_POLARITY);
+        serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
+ 
+	/* Release the PORT that this driver is using */
+	DEBUG( ircc_debug, 
+	       __FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase);
+
+	release_region( idev->io.iobase, idev->io.io_ext);
+
+	if ( idev->io.iobase2) {
+		DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", 
+		       idev->io.iobase2);
+		release_region( idev->io.iobase2, idev->io.io_ext2);
+	}
+
+	irda_device_close( idev);
+
+	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	return 0;
+}
+
+/*
+ * Function ircc_probe (iobase, board_addr, irq, dma)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+static int ircc_probe( int iobase, int iobase2) 
+{
+	int version = 1;
+	int low, high, chip, config, dma, irq;
+	
+	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+	register_bank(iobase, 3);
+	high = serial_in(iobase, UART_ID_HIGH);
+	low = serial_in(iobase, UART_ID_LOW);
+	chip = serial_in(iobase, UART_CHIP_ID);
+	version = serial_in(iobase, UART_VERSION);
+	config = serial_in(iobase, UART_INTERFACE);
+	irq = config >> 4 & 0x0f;
+	dma = config & 0x0f;
+
+	if (high == 0x10 && low == 0xb8 && chip == 0xf1) {
+		DEBUG(0, "SMC IrDA Controller found; version = %d, "
+		      "port 0x%04x, dma %d, interrupt %d\n",
+		      version, iobase, dma, irq);
+	} else {
+		return -1;
+	}
+
+	serial_out(iobase, UART_MASTER, 0);
+
+	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+
+	return config;
+}
+
+/*
+ * Function ircc_change_speed (idev, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void ircc_change_speed( struct irda_device *idev, int speed)
+{
+	struct ircc_cb *self;
+	int iobase, ir_mode, select, fast; 
+
+	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	self = idev->priv;
+	iobase = idev->io.iobase;
+
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
+	switch ( speed) {
+	case 9600:
+	case 19200:
+	case 37600:
+	case 57600:
+	case 115200:
+	        DEBUG(ircc_debug+1, 
+		      __FUNCTION__ ": using irport to change speed to %d\n",
+		      speed);
+		register_bank(iobase, 0);
+		serial_out(iobase, UART_IER, 0);
+		serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+		serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+		irport_start(idev, idev->io.iobase2);
+		irport_change_speed( idev, speed);
+		return;
+		break;
+
+	case 576000:		
+		ir_mode = UART_CFGA_IRDA_HDLC;
+		select = 0;
+		fast = 0;
+		DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+		break;
+	case 1152000:
+		ir_mode = UART_CFGA_IRDA_HDLC;
+		select = UART_1152;
+		fast = 0;
+		DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+		break;
+	case 4000000:
+		ir_mode = UART_CFGA_IRDA_4PPM;
+		select = 0;
+		fast = UART_LCR_A_FAST;
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 07'
echo 'File patch-2.2.10 is continued in part 08'
echo 08 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 06 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
+			else
+				info->input_signal_events.dsr_down++;
+		}
X 		if (status & MISCSTATUS_DCD_LATCHED) {
+			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
+				usc_DisablestatusIrqs(info,SICR_DCD);
X 			icount->dcd++;
+			if ( status & MISCSTATUS_DCD )
+				info->input_signal_events.dcd_up++;
+			else
+				info->input_signal_events.dcd_down++;
X #ifdef CONFIG_HARD_PPS
X 			if ((info->flags & ASYNC_HARDPPS_CD) &&
X 			    (status & MISCSTATUS_DCD_LATCHED))
@@ -1369,7 +1470,15 @@
X #endif
X 		}
X 		if (status & MISCSTATUS_CTS_LATCHED)
+		{
+			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
+				usc_DisablestatusIrqs(info,SICR_CTS);
X 			icount->cts++;
+			if ( status & MISCSTATUS_CTS )
+				info->input_signal_events.cts_up++;
+			else
+				info->input_signal_events.cts_down++;
+		}
X 		wake_up_interruptible(&info->status_event_wait_q);
X 		wake_up_interruptible(&info->event_wait_q);
X 
@@ -1411,6 +1520,8 @@
X 		}
X 	}
X 
+	mgsl_bh_queue_put(info, BH_TYPE_STATUS, status);
+	
X 	/* for diagnostics set IRQ flag */
X 	if ( status & MISCSTATUS_TXC_LATCHED ){
X 		usc_OutReg( info, SICR,
@@ -1642,8 +1753,10 @@
X 	/* Post a receive event for BH processing. */
X 	mgsl_bh_queue_put( info, BH_TYPE_RECEIVE_DMA, status );
X 	
-	if ( status & BIT3 )
+	if ( status & BIT3 ) {
X 		info->rx_overflow = 1;
+		info->icount.buf_overrun++;
+	}
X 
X }	/* end of mgsl_isr_receive_dma() */
X 
@@ -1696,9 +1809,9 @@
X 		if ( info->isr_overflow ) {
X 			printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n",
X 				__FILE__,__LINE__,info->device_name, irq);
-				/* Interrupt overflow. Reset adapter and exit. */
-//				UscReset(info);
-//				break;
+			usc_DisableMasterIrqBit(info);
+			usc_DisableDmaInterrupts(info,DICR_MASTER);
+			break;
X 		}
X 	}
X 	
@@ -1980,6 +2093,11 @@
X 		usc_set_async_mode(info);
X 		
X 	usc_set_serial_signals(info);
+	
+	info->dcd_chkcount = 0;
+	info->cts_chkcount = 0;
+	info->ri_chkcount = 0;
+	info->dsr_chkcount = 0;
X 
X 	/* enable modem signal IRQs and read initial signal states */
X 	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);		
@@ -2112,16 +2230,27 @@
X 
X 	if ( info->params.mode == MGSL_MODE_HDLC ) {
X 		/* operating in synchronous (frame oriented) mode */
-	
+
X 		if (info->tx_active) {
X 			ret = 0; goto cleanup; 
X 		}
-		
+	
+		/* if operating in HDLC LoopMode and the adapter  */
+		/* has yet to be inserted into the loop, we can't */
+		/* transmit					  */
+
+		if ( (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) &&
+			!usc_loopmode_active(info) )
+		{
+			ret = 0;
+			goto cleanup;
+		}
+
X 		if ( info->xmit_cnt ) {
X 			/* Send accumulated from send_char() calls */
X 			/* as frame and wait before accepting more data. */
X 			ret = 0;
-				
+			
X 			/* copy data from circular xmit_buf to */
X 			/* transmit DMA buffer. */
X 			mgsl_load_tx_dma_buffer(info,
@@ -2578,8 +2707,19 @@
X 			
X 	spin_lock_irqsave(&info->irq_spinlock,flags);
X 	if ( enable ) {
-		if ( !info->tx_enabled )
+		if ( !info->tx_enabled ) {
+
X 			usc_start_transmitter(info);
+			/*--------------------------------------------------
+			 * if HDLC/SDLC Loop mode, attempt to insert the
+			 * station in the 'loop' by setting CMR:13. Upon
+			 * receipt of the next GoAhead (RxAbort) sequence,
+			 * the OnLoop indicator (CCSR:7) should go active
+			 * to indicate that we are on the loop
+			 *--------------------------------------------------*/
+			if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+				usc_loopmode_insert_request( info );
+		}
X 	} else {
X 		if ( info->tx_enabled )
X 			usc_stop_transmitter(info);
@@ -2604,7 +2744,12 @@
X 			
X 	spin_lock_irqsave(&info->irq_spinlock,flags);
X 	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC )
-		usc_TCmd(info,TCmd_SendAbort);
+	{
+		if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+			usc_loopmode_cancel_transmit( info );
+		else
+			usc_TCmd(info,TCmd_SendAbort);
+	}
X 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
X 	return 0;
X 	
@@ -2640,25 +2785,39 @@
X /* mgsl_wait_event() 	wait for specified event to occur
X  * 	
X  * Arguments:	 	info	pointer to device instance data
- * 			mask	bitmask of events to wait for
- * Return Value:	bit mask of triggering event, otherwise error code
+ * 			mask	pointer to bitmask of events to wait for
+ * Return Value:	0 	if successful and bit mask updated with
+ *				of events triggerred,
+ * 			otherwise error code
X  */
-static int mgsl_wait_event(struct mgsl_struct * info, int mask)
+static int mgsl_wait_event(struct mgsl_struct * info, int * mask_ptr)
X {
X  	unsigned long flags;
X 	int s;
X 	int rc=0;
X 	u16 regval;
X 	struct mgsl_icount cprev, cnow;
+	int events = 0;
+	int mask;
+	struct	_input_signal_events signal_events_prev, signal_events_now;
+
+	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
+	if (rc) {
+		return  -EFAULT;
+	}
X 		 
X 	if (debug_level >= DEBUG_LEVEL_INFO)
X 		printk("%s(%d):mgsl_wait_event(%s,%d)\n", __FILE__,__LINE__,
X 			info->device_name, mask);
-			
+
X 	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
+
+	usc_get_serial_signals(info);
+	s = info->serial_signals;
+
X 	/* note the counters on entry */
X 	cprev = info->icount;
+	signal_events_prev = info->input_signal_events;
X 	
X 	if (mask & MgslEvent_ExitHuntMode) {
X 		/* enable exit hunt mode IRQ */
@@ -2676,7 +2835,22 @@
X 	
X 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
X 	
-	while(!rc) {
+	/* Determine if any user requested events for input signals is currently TRUE */
+	
+	events |= (mask & ((s & SerialSignal_DSR) ?
+			MgslEvent_DsrActive:MgslEvent_DsrInactive));
+
+	events |= (mask & ((s & SerialSignal_DCD) ?
+			MgslEvent_DcdActive:MgslEvent_DcdInactive));
+		
+	events |= (mask & ((s & SerialSignal_CTS) ?
+			MgslEvent_CtsActive:MgslEvent_CtsInactive));
+		
+	events |= (mask & ((s & SerialSignal_RI) ?
+			MgslEvent_RiActive:MgslEvent_RiInactive));
+	
+
+	while(!events) {
X 		/* sleep until event occurs */
X 		interruptible_sleep_on(&info->event_wait_q);
X 		
@@ -2687,44 +2861,57 @@
X 		}
X 			
X 		spin_lock_irqsave(&info->irq_spinlock,flags);
+
X 		/* get icount and serial signal states */
X 		cnow = info->icount;
-		s = info->serial_signals;
+		signal_events_now = info->input_signal_events;
X 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+		if (signal_events_now.dsr_up != signal_events_prev.dsr_up && 
+				mask & MgslEvent_DsrActive )
+			events |= MgslEvent_DsrActive;
+		
+		if (signal_events_now.dsr_down != signal_events_prev.dsr_down && 
+				mask & MgslEvent_DsrInactive )
+			events |= MgslEvent_DsrInactive;
+
+		if (signal_events_now.dcd_up != signal_events_prev.dcd_up &&
+				mask & MgslEvent_DcdActive )
+			events |= MgslEvent_DcdActive;
+		
+		if (signal_events_now.dcd_down != signal_events_prev.dcd_down &&
+				mask & MgslEvent_DcdInactive )
+			events |= MgslEvent_DcdInactive;
+		
+		if (signal_events_now.cts_up != signal_events_prev.cts_up &&
+				mask & MgslEvent_CtsActive )
+			events |= MgslEvent_CtsActive;
+		
+		if (signal_events_now.cts_down != signal_events_prev.cts_down &&
+				mask & MgslEvent_CtsInactive )
+			events |= MgslEvent_CtsInactive;
+		
+		if (signal_events_now.ri_up != signal_events_prev.ri_up &&
+				mask & MgslEvent_RiActive )
+			events |= MgslEvent_RiActive;
+		
+		if (signal_events_now.ri_down != signal_events_prev.ri_down &&
+				mask & MgslEvent_RiInactive )
+			events |= MgslEvent_RiInactive;
X 		
-		rc = 0;		
-		
-		if (cnow.dsr != cprev.dsr)
-			rc |= (mask & ((s & SerialSignal_DSR) ?
-				MgslEvent_DsrActive:MgslEvent_DsrInactive));
-		
-		if (cnow.dcd != cprev.dcd)
-			rc |= (mask & ((s & SerialSignal_DCD) ?
-				MgslEvent_DcdActive:MgslEvent_DcdInactive));
-				
-		if (cnow.cts != cprev.cts)
-			rc |= (mask & ((s & SerialSignal_CTS) ?
-				MgslEvent_CtsActive:MgslEvent_CtsInactive));
-				
-		if (cnow.rng != cprev.rng)
-			rc |= (mask & ((s & SerialSignal_RI) ?
-				MgslEvent_RiActive:MgslEvent_RiInactive));
-				
X 		if (cnow.exithunt != cprev.exithunt)
-			rc |= (mask & MgslEvent_ExitHuntMode);
-			
+			events |= (mask & MgslEvent_ExitHuntMode);
+
X 		if (cnow.rxidle != cprev.rxidle)
-			rc |= (mask & MgslEvent_ExitHuntMode);
-				
-		if (!rc)
-			rc = -EIO; /* no change => error */
-			
+			events |= (mask & MgslEvent_IdleReceived);
+		
X 		cprev = cnow;
+		signal_events_prev = signal_events_now;
X 	}
X 	
X 	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
X 		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!info->event_wait_q) {
+		if (!waitqueue_active(&info->event_wait_q)) {
X 			/* disable enable exit hunt mode/idle rcvd IRQs */
X 			regval = usc_InReg(info,RICR);
X 			usc_OutReg(info, RICR, regval & 
@@ -2732,7 +2919,10 @@
X 		}
X 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
X 	}
-	
+
+	if ( rc == 0 )
+		PUT_USER(rc, events, mask_ptr);
+		
X 	return rc;
X 	
X }	/* end of mgsl_wait_event() */
@@ -2772,7 +2962,7 @@
X 
X 	if (debug_level >= DEBUG_LEVEL_INFO)
X 		printk("%s(%d):mgsl_get_modem_info %s value=%08X\n",
-			 __FILE__,__LINE__, info->device_name, *value );
+			 __FILE__,__LINE__, info->device_name, result );
X 			
X 	PUT_USER(err,result,value);
X 	return err;
@@ -2928,7 +3118,9 @@
X 		case MGSL_IOCGSTATS:
X 			return mgsl_get_stats(info,(struct mgsl_icount*)arg);
X 		case MGSL_IOCWAITEVENT:
-			return mgsl_wait_event(info,(int)arg);
+			return mgsl_wait_event(info,(int*)arg);
+		case MGSL_IOCLOOPTXDONE:
+			return mgsl_loopmode_send_done(info);
X 		case MGSL_IOCCLRMODCOUNT:
X 			while(MOD_IN_USE)
X 				MOD_DEC_USE_COUNT;
@@ -3626,11 +3818,6 @@
X 	}
X 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
X 	
-#if 0 && LINUX_VERSION_CODE >= VERSION(2,1,0)
-	ret += sprintf(buf+ret, "irq_spinlock=%08X\n",
-	 		info->irq_spinlock.lock );
-#endif
-	
X 	return ret;
X 	
X }	/* end of line_info() */
@@ -4223,6 +4410,18 @@
X 			if ( PCIBIOS_SUCCESSFUL == pcibios_find_device(
X 				MICROGATE_VENDOR_ID, SYNCLINK_DEVICE_ID, i, &bus, &func) ) {
X 				
+#if LINUX_VERSION_CODE >= VERSION(2,1,0)
+				struct pci_dev *pdev = pci_find_slot(bus,func);
+				irq_line = pdev->irq;				
+#else												
+				if (pcibios_read_config_byte(bus,func,
+					PCI_INTERRUPT_LINE,&irq_line) ) {
+					printk( "%s(%d):USC I/O addr not set.\n",
+						__FILE__,__LINE__);
+					continue;
+				}
+#endif
+
X 				if (pcibios_read_config_dword(bus,func,
X 					PCI_BASE_ADDRESS_3,&shared_mem_base) ) {
X 					printk( "%s(%d):Shared mem addr not set.\n",
@@ -4244,13 +4443,6 @@
X 					continue;
X 				}
X 				
-				if (pcibios_read_config_byte(bus,func,
-					PCI_INTERRUPT_LINE,&irq_line) ) {
-					printk( "%s(%d):USC I/O addr not set.\n",
-						__FILE__,__LINE__);
-					continue;
-				}
-				
X 				info = mgsl_allocate_device();
X 				if ( !info ) {
X 					/* error allocating device instance data */
@@ -4667,29 +4859,53 @@
X {
X 	u16 RegValue;
X 
-	/* Channel mode Register (CMR)
-	 *
-	 * <15..14>  00    Tx Sub modes, Underrun Action
-	 * <13>      0     1 = Send Preamble before opening flag
-	 * <12>      0     1 = Consecutive Idles share common 0
-	 * <11..8>   0110  Transmitter mode = HDLC/SDLC
-	 * <7..4>    0000  Rx Sub modes, addr/ctrl field handling
-	 * <3..0>    0110  Receiver mode = HDLC/SDLC
-	 *
-	 * 0000 0110 0000 0110 = 0x0606
-	 */
+ 	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+ 	{
+ 	   /*
+ 	   ** Channel Mode Register (CMR)
+ 	   **
+ 	   ** <15..14>    10    Tx Sub Modes, Send Flag on Underrun
+ 	   ** <13>        0     0 = Transmit Disabled (initially)
+ 	   ** <12>        0     1 = Consecutive Idles share common 0
+ 	   ** <11..8>     1110  Transmitter Mode = HDLC/SDLC Loop
+ 	   ** <7..4>      0000  Rx Sub Modes, addr/ctrl field handling
+ 	   ** <3..0>      0110  Receiver Mode = HDLC/SDLC
+ 	   **
+ 	   ** 1000 1110 0000 0110 = 0x8e06
+ 	   */
+ 	   RegValue = 0x8e06;
+ 
+ 	   /*--------------------------------------------------
+ 	    * ignore user options for UnderRun Actions and
+ 	    * preambles
+ 	    *--------------------------------------------------*/
+ 	}
+ 	else
+ 	{	
+		/* Channel mode Register (CMR)
+		 *
+		 * <15..14>  00    Tx Sub modes, Underrun Action
+		 * <13>      0     1 = Send Preamble before opening flag
+		 * <12>      0     1 = Consecutive Idles share common 0
+		 * <11..8>   0110  Transmitter mode = HDLC/SDLC
+		 * <7..4>    0000  Rx Sub modes, addr/ctrl field handling
+		 * <3..0>    0110  Receiver mode = HDLC/SDLC
+		 *
+		 * 0000 0110 0000 0110 = 0x0606
+		 */
X 
-	RegValue = 0x0606;
+		RegValue = 0x0606;
X 
-	if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 )
-		RegValue |= BIT14;
-	else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
-		RegValue |= BIT15;
-	else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
-		RegValue |= BIT15 + BIT14;
+		if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 )
+			RegValue |= BIT14;
+		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
+			RegValue |= BIT15;
+		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
+			RegValue |= BIT15 + BIT14;
X 
-	if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
-		RegValue |= BIT13;
+		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
+			RegValue |= BIT13;
+	}
X 
X 	if ( info->params.flags & HDLC_FLAG_SHARE_ZERO )
X 		RegValue |= BIT12;
@@ -4858,6 +5074,8 @@
X 		RegValue |= 0x0003;	/* RxCLK from DPLL */
X 	else if ( info->params.flags & HDLC_FLAG_RXC_BRG )
X 		RegValue |= 0x0004;	/* RxCLK from BRG0 */
+ 	else if ( info->params.flags & HDLC_FLAG_RXC_TXCPIN)
+ 		RegValue |= 0x0006;	/* RxCLK from TXC Input */
X 	else
X 		RegValue |= 0x0007;	/* RxCLK from Port1 */
X 
@@ -4865,6 +5083,8 @@
X 		RegValue |= 0x0018;	/* TxCLK from DPLL */
X 	else if ( info->params.flags & HDLC_FLAG_TXC_BRG )
X 		RegValue |= 0x0020;	/* TxCLK from BRG0 */
+ 	else if ( info->params.flags & HDLC_FLAG_TXC_RXCPIN)
+ 		RegValue |= 0x0038;	/* RxCLK from TXC Input */
X 	else
X 		RegValue |= 0x0030;	/* TxCLK from Port0 */
X 
@@ -4918,10 +5138,24 @@
X 		/*  of rounding up and then subtracting 1 we just don't subtract */
X 		/*  the one in this case. */
X 
-		Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed);
-		if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2)
-		       / info->params.clock_speed) )
-			Tc--;
+ 		/*--------------------------------------------------
+ 		 * ejz: for DPLL mode, application should use the
+ 		 * same clock speed as the partner system, even 
+ 		 * though clocking is derived from the input RxData.
+ 		 * In case the user uses a 0 for the clock speed,
+ 		 * default to 0xffffffff and don't try to divide by
+ 		 * zero
+ 		 *--------------------------------------------------*/
+ 		if ( info->params.clock_speed )
+ 		{
+			Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed);
+			if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2)
+			       / info->params.clock_speed) )
+				Tc--;
+ 		}
+ 		else
+ 			Tc = -1;
+ 				  
X 
X 		/* Write 16-bit Time Constant for BRG1 */
X 		usc_OutReg( info, TC1R, Tc );
@@ -6324,6 +6558,13 @@
X 	if ( debug_level >= DEBUG_LEVEL_DATA )
X 		mgsl_trace_block(info,Buffer,BufferSize,1);	
X 
+	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
+		/* set CMR:13 to start transmit when
+		 * next GoAhead (abort) is received
+		 */
+	 	info->cmr_value |= BIT13;			  
+	}
+		
X 	/* Setup the status and RCC (Frame Size) fields of the 1st */
X 	/* buffer entry in the transmit DMA buffer list. */
X 
@@ -6377,7 +6618,7 @@
X 	unsigned int i;
X 	BOOLEAN rc = TRUE;
X 	unsigned long flags;
-	
+
X 	spin_lock_irqsave(&info->irq_spinlock,flags);
X 	usc_reset(info);
X 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
@@ -6467,7 +6708,7 @@
X 	usc_reset(info);
X 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
X 	
-	if ( !info->irq_occurred )
+	if ( !info->irq_occurred ) 
X 		return FALSE;
X 	else
X 		return TRUE;
@@ -6495,7 +6736,7 @@
X 	volatile unsigned long EndTime;
X 	unsigned long flags;
X 	MGSL_PARAMS tmp_params;
-	
+
X 	/* save current port options */
X 	memcpy(&tmp_params,&info->params,sizeof(MGSL_PARAMS));
X 	/* load default port options */
@@ -6653,7 +6894,7 @@
X 	/**********************************/
X 	/* WAIT FOR TRANSMIT FIFO TO FILL */
X 	/**********************************/
-															 
+	
X 	/* Wait 100ms */
X 	EndTime = jiffies + jiffies_from_ms(100);
X 
@@ -6720,7 +6961,7 @@
X 
X 	if ( rc == TRUE ){
X 		/* CHECK FOR TRANSMIT ERRORS */
-		if ( status & (BIT5 + BIT1) )
+		if ( status & (BIT5 + BIT1) ) 
X 			rc = FALSE;
X 	}
X 
@@ -6977,13 +7218,90 @@
X 	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
X 		info->icount.txtimeout++;
X 	}
-	
X 	spin_lock_irqsave(&info->irq_spinlock,flags);
X 	info->tx_active = 0;
X 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+		usc_loopmode_cancel_transmit( info );
+
X 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
X 	
X 	mgsl_bh_transmit_data(info,0);
X 	
X }	/* end of mgsl_tx_timeout() */
+
+/* signal that there are no more frames to send, so that
+ * line is 'released' by echoing RxD to TxD when current
+ * transmission is complete (or immediately if no tx in progress).
+ */
+static int mgsl_loopmode_send_done( struct mgsl_struct * info )
+{
+	unsigned long flags;
+	
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
+		if (info->tx_active)
+			info->loopmode_send_done_requested = TRUE;
+		else
+			usc_loopmode_send_done(info);
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return 0;
+}
+
+/* release the line by echoing RxD to TxD
+ * upon completion of a transmit frame
+ */
+void usc_loopmode_send_done( struct mgsl_struct * info )
+{
+ 	info->loopmode_send_done_requested = FALSE;
+ 	/* clear CMR:13 to 0 to start echoing RxData to TxData */
+ 	info->cmr_value &= ~BIT13;			  
+ 	usc_OutReg(info, CMR, info->cmr_value);
+}
+
+/* abort a transmit in progress while in HDLC LoopMode
+ */
+void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
+{
+ 	/* reset tx dma channel and purge TxFifo */
+ 	usc_RTCmd( info, RTCmd_PurgeTxFifo );
+ 	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
+  	usc_loopmode_send_done( info );
+}
+
+/* for HDLC/SDLC LoopMode, setting CMR:13 after the transmitter is enabled
+ * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort)
+ * we must clear CMR:13 to begin repeating TxData to RxData
+ */
+void usc_loopmode_insert_request( struct mgsl_struct * info )
+{
+ 	info->loopmode_insert_requested = TRUE;
+ 
+ 	/* enable RxAbort irq. On next RxAbort, clear CMR:13 to
+ 	 * begin repeating TxData on RxData (complete insertion)
+	 */
+ 	usc_OutReg( info, RICR, 
+		(usc_InReg( info, RICR ) | RXSTATUS_ABORT_RECEIVED ) );
+		
+	/* set CMR:13 to insert into loop on next GoAhead (RxAbort) */
+	info->cmr_value |= BIT13;
+ 	usc_OutReg(info, CMR, info->cmr_value);
+}
+
+/* return 1 if station is inserted into the loop, otherwise 0
+ */
+int usc_loopmode_active( struct mgsl_struct * info)
+{
+ 	return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
+}
+
+/* return 1 if USC is in loop send mode, otherwise 0
+ */
+int usc_loopmode_send_active( struct mgsl_struct * info )
+{
+	return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ;
+}			  
X 
diff -u --recursive --new-file v2.2.9/linux/drivers/char/tuner.c linux/drivers/char/tuner.c
--- v2.2.9/linux/drivers/char/tuner.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/tuner.c	Mon Jun  7 16:18:17 1999
@@ -84,7 +84,9 @@
X 	      //  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
X 	        16*170.00,16*450.00,0x02,0x04,0x01,0x8e,0xc2,623},
X 	{"Temic 4036 FY5 NTSC", TEMIC, NTSC,
-		16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
+	        16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
+        {"Alps HSBH1", TEMIC, NTSC,
+                16*137.25,16*385.25,0x01,0x02,0x08,0x8e,0xc2,732},
X };
X 
X /* ---------------------------------------------------------------------- */
diff -u --recursive --new-file v2.2.9/linux/drivers/char/tuner.h linux/drivers/char/tuner.h
--- v2.2.9/linux/drivers/char/tuner.h	Thu Nov 12 16:21:19 1998
+++ linux/drivers/char/tuner.h	Mon Jun  7 16:18:17 1999
@@ -31,6 +31,7 @@
X #define TUNER_TEMIC_NTSC    6
X #define TUNER_TEMIC_PAL_I   7
X #define TUNER_TEMIC_4036FY5_NTSC	8
+#define TUNER_ALPS_TSBH1_NTSC 9
X 
X #define NOTUNER 0
X #define PAL     1
diff -u --recursive --new-file v2.2.9/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.2.9/linux/drivers/char/videodev.c	Fri Apr 16 14:47:30 1999
+++ linux/drivers/char/videodev.c	Wed Jun  2 11:29:28 1999
@@ -9,7 +9,7 @@
X  *		as published by the Free Software Foundation; either version
X  *		2 of the License, or (at your option) any later version.
X  *
- * Author:	Alan Cox, <al...@cymru.net>
+ * Author:	Alan Cox, <al...@redhat.com>
X  *
X  * Fixes:
X  */
diff -u --recursive --new-file v2.2.9/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.2.9/linux/drivers/char/wdt.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/char/wdt.c	Wed Jun  2 11:29:28 1999
@@ -1,8 +1,8 @@
X /*
X  *	Industrial Computer Source WDT500/501 driver for Linux 2.1.x
X  *
- *	(c) Copyright 1996-1997 Alan Cox <al...@cymru.net>, All Rights Reserved.
- *				http://www.cymru.net
+ *	(c) Copyright 1996-1997 Alan Cox <al...@redhat.com>, All Rights Reserved.
+ *				http://www.redhat.com
X  *
X  *	This program is free software; you can redistribute it and/or
X  *	modify it under the terms of the GNU General Public License
@@ -15,7 +15,7 @@
X  *
X  *	(c) Copyright 1995    Alan Cox <al...@lxorguk.ukuu.org.uk>
X  *
- *	Release 0.07.
+ *	Release 0.08.
X  *
X  *	Fixes
X  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -24,6 +24,8 @@
X  *					Matt Crocker).
X  *		Alan Cox	:	Added wdt= boot option
X  *		Alan Cox	:	Cleaned up copy/user stuff
+ *		Tim Hockin	:	Added insmod parameters, comment cleanup
+ *					Parameterized timeout
X  */
X 
X #include <linux/config.h>
diff -u --recursive --new-file v2.2.9/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.2.9/linux/drivers/misc/parport_pc.c	Tue May 11 13:10:29 1999
+++ linux/drivers/misc/parport_pc.c	Tue Jun  1 16:43:43 1999
@@ -371,12 +371,12 @@
X 	 * copy. Some ports _do_ allow reads, so bypass the software
X 	 * copy here.  In addition, some bits aren't writable. */
X 	r = inb (pb->base+CONTROL);
-	if ((r & 0x3f) == w) {
+	if ((r & 0xf) == w) {
X 		w = 0xe;
X 		parport_pc_write_control (pb, w);
X 		r = inb (pb->base+CONTROL);
X 		parport_pc_write_control (pb, 0xc);
-		if ((r & 0x3f) == w)
+		if ((r & 0xf) == w)
X 			return PARPORT_MODE_PCSPP;
X 	}
X 
@@ -832,8 +832,11 @@
X 		 * Put the ECP detected port in the more SPP like mode.
X 		 */
X 		parport_pc_write_econtrol(p, 0x0);
-	parport_pc_write_control(p, 0xc);
+	parport_pc_write_control(p, 0x8);
X 	parport_pc_write_data(p, 0);
+	udelay (50);
+	parport_pc_write_control(p, 0xc);
+	udelay (50);
X 
X 	if (parport_probe_hook)
X 		(*parport_probe_hook)(p);
diff -u --recursive --new-file v2.2.9/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.2.9/linux/drivers/misc/parport_share.c	Sun Nov  8 14:02:59 1998
+++ linux/drivers/misc/parport_share.c	Mon Jun  7 14:49:10 1999
@@ -298,9 +298,9 @@
X 	port = dev->port;
X 
X 	if (port->cad == dev) {
-		printk(KERN_WARNING "%s: refused to unregister "
-		       "currently active device %s.\n", port->name, dev->name);
-		return;
+		printk(KERN_DEBUG "%s: %s forgot to release port\n",
+		       port->name, dev->name);
+		parport_release (dev);
X 	}
X 
X 	spin_lock(&port->pardevice_lock);
diff -u --recursive --new-file v2.2.9/linux/drivers/net/3c515.c linux/drivers/net/3c515.c
--- v2.2.9/linux/drivers/net/3c515.c	Fri Jan  8 22:36:06 1999
+++ linux/drivers/net/3c515.c	Mon Jun  7 16:19:58 1999
@@ -1009,6 +1009,7 @@
X 			outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
X 		}
X 	}
+	vp->stats.tx_bytes+=skb->len;
X 	return 0;
X }
X 
@@ -1209,6 +1210,7 @@
X 				netif_rx(skb);
X 				dev->last_rx = jiffies;
X 				vp->stats.rx_packets++;
+				vp->stats.rx_bytes+=skb->len;
X 				/* Wait a limited time to go to next packet. */
X 				for (i = 200; i >= 0; i--)
X 					if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
@@ -1256,6 +1258,7 @@
X 			short pkt_len = rx_status & 0x1fff;
X 			struct sk_buff *skb;
X 
+			vp->stats.rx_bytes+=pkt_len;
X 			if (vortex_debug > 4)
X 				printk("Receiving packet size %d status %4.4x.\n",
X 					   pkt_len, rx_status);
diff -u --recursive --new-file v2.2.9/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.2.9/linux/drivers/net/Config.in	Tue Mar 23 14:35:47 1999
+++ linux/drivers/net/Config.in	Mon Jun  7 14:35:22 1999
@@ -109,6 +109,7 @@
X   fi
X   if [ "$CONFIG_MCA" = "y" ]; then
X     tristate 'NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA
+    tristate 'SKnet MCA support' CONFIG_SKMC
X   fi
X   bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA
X   if [ "$CONFIG_NET_EISA" = "y" ]; then
diff -u --recursive --new-file v2.2.9/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.2.9/linux/drivers/net/Makefile	Fri Apr 16 14:47:30 1999
+++ linux/drivers/net/Makefile	Mon Jun  7 14:35:22 1999
@@ -486,6 +486,14 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_SKMC),y)
+L_OBJS += sk_mca.o
+else
+  ifeq ($(CONFIG_SKMC),m)
+  M_OBJS += sk_mca.o
+  endif
+endif
+
X ifeq ($(CONFIG_ELMC_II),y)
X L_OBJS += 3c527.o
X else
diff -u --recursive --new-file v2.2.9/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.2.9/linux/drivers/net/Space.c	Tue Mar 23 14:35:47 1999
+++ linux/drivers/net/Space.c	Mon Jun  7 14:35:22 1999
@@ -69,6 +69,7 @@
X extern int wavelan_probe(struct device *);
X extern int el16_probe(struct device *);
X extern int elmc_probe(struct device *);
+extern int skmca_probe(struct device *);
X extern int elplus_probe(struct device *);
X extern int ac3200_probe(struct device *);
X extern int es_probe(struct device *);
@@ -266,6 +267,9 @@
X #endif
X #ifdef CONFIG_ELMC		/* 3c523 */
X 	{elmc_probe, 0},
+#endif
+#ifdef CONFIG_SKMC              /* SKnet Microchannel */
+        {skmca_probe, 0},
X #endif
X 	{NULL, 0},
X };
diff -u --recursive --new-file v2.2.9/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.2.9/linux/drivers/net/cosa.c	Wed Mar 10 15:29:46 1999
+++ linux/drivers/net/cosa.c	Mon Jun  7 16:19:58 1999
@@ -1,7 +1,10 @@
-/* $Id: cosa.c,v 1.21 1999/02/06 19:49:18 kas Exp $ */
+/* $Id: cosa.c,v 1.24 1999/05/28 17:28:34 kas Exp $ */
X 
X /*
X  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <k...@fi.muni.cz>
+ * 
+ * 	5/25/1999 : Marcelo Tosatti <mar...@conectiva.com.br>
+ * 		fixed a deadlock in cosa_sppp_open 
X  *
X  *  This program is free software; you can redistribute it and/or modify
X  *  it under the terms of the GNU General Public License as published by
@@ -72,6 +75,10 @@
X  * The Comtrol Hostess SV11 driver by Alan Cox
X  * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
X  */
+/*
+ *     5/25/1999 : Marcelo Tosatti <mar...@conectiva.com.br>
+ *             fixed a deadlock in cosa_sppp_open
+ */
X 
X /* ---------- Headers, macros, data structures ---------- */
X 
@@ -598,6 +605,7 @@
X 	if (chan->usage != 0) {
X 		printk(KERN_WARNING "%s: sppp_open called with usage count %d\n",
X 			chan->name, chan->usage);
+		spin_unlock_irqrestore(&chan->cosa->lock, flags);
X 		return -EBUSY;
X 	}
X 	chan->setup_rx = sppp_setup_rx;
@@ -749,8 +757,13 @@
X 
X static void chardev_channel_init(struct channel_data *chan)
X {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
X 	chan->rsem = MUTEX;
X 	chan->wsem = MUTEX;
+#else
+	init_MUTEX(&chan->rsem);
+	init_MUTEX(&chan->wsem);
+#endif
X }
X 
X static long long cosa_lseek(struct file * file,
@@ -1260,8 +1273,10 @@
X 			debug_status_out(cosa, 0);
X #endif
X 		}
+		cosa_putdata8(cosa, 0);
X 		cosa_putdata8(cosa, status);
X #ifdef DEBUG_IO
+		debug_data_cmd(cosa, 0);
X 		debug_data_cmd(cosa, status);
X #endif
X 	}
@@ -1654,6 +1669,7 @@
X 				printk(KERN_WARNING
X 					"%s: No channel wants data in TX IRQ\n",
X 					cosa->name);
+				put_driver_status_nolock(cosa);
X 				clear_bit(TXBIT, &cosa->rxtx);
X 				spin_unlock_irqrestore(&cosa->lock, flags);
X 				return;
diff -u --recursive --new-file v2.2.9/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- v2.2.9/linux/drivers/net/cs89x0.c	Tue Mar 23 14:35:47 1999
+++ linux/drivers/net/cs89x0.c	Mon Jun  7 16:19:58 1999
@@ -739,7 +739,7 @@
X 		if (tickssofar < 5)
X 			return 1;
X 		if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
-			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
+			   tx_done(dev) ? "IRQ conflict ?" : "network cable problem");
X 		/* Try to restart the adaptor. */
X 		dev->tbusy=0;
X 		dev->trans_start = jiffies;
diff -u --recursive --new-file v2.2.9/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.2.9/linux/drivers/net/eexpress.c	Tue May 11 13:10:29 1999
+++ linux/drivers/net/eexpress.c	Sun May 30 10:17:03 1999
@@ -81,7 +81,20 @@
X  * ftp's, which is significantly better than I get in DOS, so the overhead of
X  * stopping and restarting the CU with each transmit is not prohibitive in
X  * practice.
+ *
+ * Update by David Woodhouse 11/5/99:
+ *
+ * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture.
+ * I assume that this is because 16-bit accesses are actually handled as two
+ * 8-bit accesses.
X  */
+
+#ifdef __alpha__
+#define LOCKUP16 1
+#endif
+#ifndef LOCKUP16
+#define LOCKUP16 0
+#endif
X   
X #include <linux/config.h>
X #include <linux/module.h>
@@ -297,7 +310,7 @@
X 	outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config);
X }
X 
-static inline short int SHADOW(short int addr)
+static inline unsigned short int SHADOW(short int addr)
X {
X 	addr &= 0x1f;
X 	if (addr > 0xf) addr += 0x3ff0;
@@ -400,7 +413,10 @@
X 	outb(0,ioaddr+SIGNAL_CA);
X 	free_irq(irq,dev);
X 	outb(i586_RST,ioaddr+EEPROM_Ctrl);
-	release_region(ioaddr,16);
+	release_region(ioaddr, EEXP_IO_EXTENT);
+	release_region(ioaddr+0x4000, 16);
+	release_region(ioaddr+0x8000, 16);
+	release_region(ioaddr+0xc000, 16);
X 
X 	MOD_DEC_USE_COUNT;
X 	return 0;
@@ -887,7 +903,7 @@
X 	struct net_local *lp = (struct net_local *)dev->priv;
X 	unsigned short ioaddr = dev->base_addr;
X 
-	if (lp->width) {
+	if (LOCKUP16 || lp->width) {
X 		/* Stop the CU so that there is no chance that it
X 		   jumps off to a bogus address while we are writing the
X 		   pointer to the next transmit packet in 8-bit mode -- 
@@ -927,7 +943,7 @@
X 	if (lp->tx_head != lp->tx_reap)
X 		dev->tbusy = 0;
X 
-	if (lp->width) {
+	if (LOCKUP16 || lp->width) {
X 		/* Restart the CU so that the packet can actually
X 		   be transmitted. (Zoltan Szilagyi 10-12-96) */
X 		scb_command(dev, SCB_CUresume);
diff -u --recursive --new-file v2.2.9/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.2.9/linux/drivers/net/ibmtr.c	Tue May 11 13:10:29 1999
+++ linux/drivers/net/ibmtr.c	Sun Jun 13 10:48:21 1999
@@ -513,7 +513,7 @@
X 	/* How much shared RAM is on adapter ? */
X #ifdef PCMCIA
X 	ti->avail_shared_ram = pcmcia_reality_check(get_sram_size(ti));
-	ibmtr_mem_base = ti->sram_base ; 
+	ibmtr_mem_base = ti->sram_base << 12 ; 
X #else
X 	ti->avail_shared_ram = get_sram_size(ti);
X #endif
@@ -833,6 +833,9 @@
X 			(int)readb(ti->srb + offsetof(struct srb_close_adapter, ret_code)));
X 
X         dev->start = 0;
+#ifdef PCMCIA
+	ti->sram = 0 ;
+#endif
X 	DPRINTK("Adapter closed.\n");
X 	MOD_DEC_USE_COUNT;
X 
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.2.9/linux/drivers/net/irda/Config.in	Wed Mar 10 15:29:46 1999
+++ linux/drivers/net/irda/Config.in	Mon Jun  7 16:19:58 1999
@@ -1,18 +1,25 @@
X mainmenu_option next_comment
X comment 'Infrared-port device drivers'
X 
-dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
-if [ "$CONFIG_IRTTY_SIR" != "n" ]; then
-  comment '   Dongle support' 
-  bool '   Serial dongle support' CONFIG_DONGLE
-  if [ "$CONFIG_DONGLE" != "n" ]; then
-    dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR
-    dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR
-    dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR
-    dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRTTY_SIR
-  fi
+comment 'SIR device drivers'
+dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
+dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
+
+comment 'FIR device drivers'
+dep_tristate 'NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
+dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+dep_tristate 'Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
+dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
+dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+
+comment 'Dongle support' 
+bool 'Serial dongle support' CONFIG_DONGLE
+if [ "$CONFIG_DONGLE" != "n" ]; then
+  dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA
+  dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA
+  dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
+  dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
+  dep_tristate '   Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
X fi
-dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
-dep_tristate '  Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
-dep_tristate '  Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
+
X endmenu
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.2.9/linux/drivers/net/irda/Makefile	Fri Apr 16 14:47:30 1999
+++ linux/drivers/net/irda/Makefile	Mon Jun  7 16:19:58 1999
@@ -20,6 +20,30 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_IRPORT_SIR),y)
+L_OBJS += irport.o
+else
+  ifeq ($(CONFIG_IRPORT_SIR),m)
+  M_OBJS += irport.o
+  endif
+endif
+
+ifeq ($(CONFIG_IRPORT_SIR),y)
+L_OBJS += irport.o
+else
+  ifeq ($(CONFIG_IRPORT_SIR),m)
+  M_OBJS += irport.o
+  endif
+endif
+
+ifeq ($(CONFIG_IRPORT_SIR),y)
+L_OBJS += irport.o
+else
+  ifeq ($(CONFIG_IRPORT_SIR),m)
+  M_OBJS += irport.o
+  endif
+endif
+
X ifeq ($(CONFIG_NSC_FIR),y)
X L_OBJS += pc87108.o
X else
@@ -44,6 +68,38 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_TOSHIBA_FIR),y)
+L_OBJS += toshoboe.o
+else
+  ifeq ($(CONFIG_TOSHIBA_FIR),m)
+  M_OBJS += toshoboe.o
+  endif
+endif
+
+ifeq ($(CONFIG_TOSHIBA_FIR),y)
+L_OBJS += toshoboe.o
+else
+  ifeq ($(CONFIG_TOSHIBA_FIR),m)
+  M_OBJS += toshoboe.o
+  endif
+endif
+
+ifeq ($(CONFIG_TOSHIBA_FIR),y)
+L_OBJS += toshoboe.o
+else
+  ifeq ($(CONFIG_TOSHIBA_FIR),m)
+  M_OBJS += toshoboe.o
+  endif
+endif
+
+ifeq ($(CONFIG_SMC_IRCC_FIR),y)
+L_OBJS += irport.o smc-ircc.o
+else
+  ifeq ($(CONFIG_SMC_IRCC_FIR),m)
+  M_OBJS += irport.o smc-ircc.o
+  endif
+endif
+
X ifeq ($(CONFIG_ESI_DONGLE),y)
X L_OBJS += esi.o
X else
@@ -73,6 +129,30 @@
X else
X   ifeq ($(CONFIG_GIRBIL_DONGLE),m)
X   M_OBJS += girbil.o
+  endif
+endif
+
+ifeq ($(CONFIG_LITELINK_DONGLE),y)
+L_OBJS += litelink.o
+else
+  ifeq ($(CONFIG_LITELINK_DONGLE),m)
+  M_OBJS += litelink.o
+  endif
+endif
+
+ifeq ($(CONFIG_LITELINK_DONGLE),y)
+L_OBJS += litelink.o
+else
+  ifeq ($(CONFIG_LITELINK_DONGLE),m)
+  M_OBJS += litelink.o
+  endif
+endif
+
+ifeq ($(CONFIG_LITELINK_DONGLE),y)
+L_OBJS += litelink.o
+else
+  ifeq ($(CONFIG_LITELINK_DONGLE),m)
+  M_OBJS += litelink.o
X   endif
X endif
X 
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.2.9/linux/drivers/net/irda/actisys.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/irda/actisys.c	Mon Jun  7 16:19:58 1999
@@ -1,16 +1,16 @@
X /*********************************************************************
X  *                
X  * Filename:      actisys.c
- * Version:       0.5
+ * Version:       0.8
X  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
X  *                dongles
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Apr 12 11:56:35 1999
+ * Modified at:   Sun May 16 14:35:11 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -29,22 +29,16 @@
X #include <linux/sched.h>
X #include <linux/init.h>
X 
-#include <asm/ioctls.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
X #include <net/irda/irda.h>
X #include <net/irda/irmod.h>
X #include <net/irda/irda_device.h>
-#include <net/irda/irtty.h>
X #include <net/irda/dongle.h>
X 
-static void actisys_reset( struct irda_device *dev, int unused);
-static void actisys_open( struct irda_device *idev, int type);
-static void actisys_close( struct irda_device *dev);
+static void actisys_reset(struct irda_device *dev);
+static void actisys_open(struct irda_device *idev, int type);
+static void actisys_close(struct irda_device *dev);
X static void actisys_change_speed( struct irda_device *dev, int baudrate);
-static void actisys_reset( struct irda_device *dev, int unused);
-static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos);
+static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos);
X 
X /* These are the baudrates supported */
X static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
@@ -58,17 +52,37 @@
X 	actisys_init_qos,
X };
X 
-__initfunc(void actisys_init(void))
+static struct dongle dongle_plus = {
+	ACTISYS_PLUS_DONGLE,
+	actisys_open,
+	actisys_close,
+	actisys_reset,
+	actisys_change_speed,
+	actisys_init_qos,
+};
+
+__initfunc(int actisys_init(void))
X {
-	irtty_register_dongle(&dongle);
+	int ret;
+
+	ret = irda_device_register_dongle(&dongle);
+	if (ret < 0)
+		return ret;
+	ret = irda_device_register_dongle(&dongle_plus);
+	if (ret < 0) {
+		irda_device_unregister_dongle(&dongle);
+		return ret;
+	}	
+	return 0;
X }
X 
X void actisys_cleanup(void)
X {
-	irtty_unregister_dongle(&dongle);
+	irda_device_unregister_dongle(&dongle);
+	irda_device_unregister_dongle(&dongle_plus);
X }
X 
-static void actisys_open( struct irda_device *idev, int type)
+static void actisys_open(struct irda_device *idev, int type)
X {
X 	strcat(idev->description, " <-> actisys");
X 
@@ -78,8 +92,11 @@
X 	MOD_INC_USE_COUNT;
X }
X 
-static void actisys_close( struct irda_device *dev)
+static void actisys_close(struct irda_device *idev)
X {
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
X 	MOD_DEC_USE_COUNT;
X }
X 
@@ -90,25 +107,16 @@
X  *    To cycle through the available baud rates, pulse RTS low for a few
X  *    ms.  
X  */
-static void actisys_change_speed( struct irda_device *idev, int baudrate)
+static void actisys_change_speed(struct irda_device *idev, int baudrate)
X {
-        struct irtty_cb *self;
-        struct tty_struct *tty;
-        struct termios old_termios;
-	int cflag;
X         int current_baudrate;
X         int index = 0;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
-	self = (struct irtty_cb *) idev->priv;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRTTY_MAGIC, return;);
-
X 	current_baudrate = idev->qos.baud_rate.value;
X 
X 	/* Find the correct baudrate index for the currently used baudrate */
@@ -117,69 +125,34 @@
X 
X         DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
X 
-	if ( !self->tty)
-		return;
-
-	tty = self->tty;
-
X 	/* Cycle through avaiable baudrates until we reach the correct one */
-        while ( current_baudrate != baudrate) {	
-                DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n",
-                       baud_rates[index]);
+        while (current_baudrate != baudrate) {	
+                DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
+		      baud_rates[index]);
X 		
X 		/* Set DTR, clear RTS */
-		irtty_set_dtr_rts(tty, TRUE, FALSE);
+		irda_device_set_dtr_rts(idev, TRUE, FALSE);
X 		
X 		/* Wait at a few ms */
X 		current->state = TASK_INTERRUPTIBLE;
X 		schedule_timeout(2);
X 
X 		/* Set DTR, Set RTS */
-		irtty_set_dtr_rts(tty, TRUE, TRUE);
+		irda_device_set_dtr_rts(idev, TRUE, TRUE);
X 		
X 		/* Wait at a few ms again */
X 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout( 2);
+		schedule_timeout(2);
X 
X                 /* Go to next baudrate */
-		if ( idev->io.dongle_id == ACTISYS_DONGLE)
+		if (idev->io.dongle_id == ACTISYS_DONGLE)
X                         index = (index+1) % 4; /* IR-220L */
X 		else
X                         index = (index+1) % 5; /* IR-220L+ */
X 
X                 current_baudrate = baud_rates[index];
X         }
-	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", 
-	      baud_rates[index]);
-
-	/* Now change the speed of the serial port */
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
-        switch ( baudrate) {
-        case 9600:
-        default:
-		cflag |= B9600;
-		break;
-	case 19200:
-		cflag |= B19200;
-		break;
-	case 38400:
-		cflag |= B38400;
-		break;
-	case 57600:
-		cflag |= B57600;
-		break;
-	case 115200:
-		cflag |= B115200;
-		break;
-	}
-
-	/* Change speed of serial port */
-	tty->termios->c_cflag = cflag;
-	tty->driver.set_termios( tty, &old_termios);
+	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",baud_rates[index]);
X }
X 
X /*
@@ -191,32 +164,20 @@
X  *    	1. Clear DTR for a few ms.
X  *
X  */
-static void actisys_reset( struct irda_device *idev, int unused)
+static void actisys_reset(struct irda_device *idev)
X {
-	struct irtty_cb *self;
-        struct tty_struct *tty;
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) idev->priv;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRTTY_MAGIC, return;);
-
-	tty = self->tty;
-	if ( !tty)
-		return;
-
X 	/* Clear DTR */
-	irtty_set_dtr_rts(tty, FALSE, TRUE);
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
X 
X 	/* Sleep 10-20 ms*/
X 	current->state = TASK_INTERRUPTIBLE;
X 	schedule_timeout(2);
X 	
X 	/* Go back to normal mode */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
X 	
X 	idev->qos.baud_rate.value = 9600;
X }
@@ -227,12 +188,12 @@
X  *    Initialize QoS capabilities
X  *
X  */
-static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos)
+static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos)
X {
X 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
X 
X 	/* Remove support for 38400 if this is not a 220L+ dongle */
-	if ( idev->io.dongle_id == ACTISYS_DONGLE)
+	if (idev->io.dongle_id == ACTISYS_DONGLE)
X 		qos->baud_rate.bits &= ~IR_38400;
X 	
X 	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
@@ -251,8 +212,7 @@
X  */
X int init_module(void)
X {
-	actisys_init();
-	return(0);
+	return actisys_init();
X }
X 
X /*
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.2.9/linux/drivers/net/irda/esi.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/irda/esi.c	Mon Jun  7 16:19:59 1999
@@ -1,17 +1,17 @@
X /*********************************************************************
X  *                
X  * Filename:      esi.c
- * Version:       1.2
+ * Version:       1.4
X  * Description:   Driver for the Extended Systems JetEye PC dongle
X  * Status:        Experimental.
X  * Author:        Thomas Davis, <rat...@radiks.net>
X  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Mon Apr 12 11:55:30 1999
+ * Modified at:   Sun May 16 14:35:21 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:	  esi.c
X  *
+ *     Copyright (c) 1998-1999, Dag Brattli, <da...@cs.uit.no>
X  *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>,
- *     Copyright (c) 1998, Dag Brattli,  <da...@cs.uit.no>
X  *     All Rights Reserved.
X  *
X  *     This program is free software; you can redistribute it and/or
@@ -31,21 +31,17 @@
X #include <linux/sched.h>
X #include <linux/init.h>
X 
-#include <asm/ioctls.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
X #include <net/irda/irda.h>
X #include <net/irda/irmod.h>
X #include <net/irda/irda_device.h>
X #include <net/irda/irtty.h>
X #include <net/irda/dongle.h>
X 
-static void esi_open( struct irda_device *idev, int type);
-static void esi_close( struct irda_device *driver);
-static void esi_change_speed( struct irda_device *idev, int baud);
-static void esi_reset( struct irda_device *idev, int unused);
-static void esi_qos_init( struct irda_device *idev, struct qos_info *qos);
+static void esi_open(struct irda_device *idev, int type);
+static void esi_close(struct irda_device *driver);
+static void esi_change_speed(struct irda_device *idev, int baud);
+static void esi_reset(struct irda_device *idev);
+static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
X 
X static struct dongle dongle = {
X 	ESI_DONGLE,
@@ -58,17 +54,17 @@
X 
X __initfunc(int esi_init(void))
X {
-	return irtty_register_dongle(&dongle);
+	return irda_device_register_dongle(&dongle);
X }
X 
X void esi_cleanup(void)
X {
-	irtty_unregister_dongle( &dongle);
+	irda_device_unregister_dongle(&dongle);
X }
X 
-static void esi_open( struct irda_device *idev, int type)
+static void esi_open(struct irda_device *idev, int type)
X {
-	strcat( idev->description, " <-> esi");
+	strcat(idev->description, " <-> esi");
X 
X 	idev->io.dongle_id = type;
X 	idev->flags |= IFF_DONGLE;
@@ -76,8 +72,11 @@
X 	MOD_INC_USE_COUNT;
X }
X 
-static void esi_close( struct irda_device *driver)
-{
+static void esi_close(struct irda_device *idev)
+{		
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
X 	MOD_DEC_USE_COUNT;
X }
X 
@@ -87,57 +86,33 @@
X  *    Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
X  *
X  */
-static void esi_change_speed( struct irda_device *idev, int baud)
+static void esi_change_speed(struct irda_device *idev, int baud)
X {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
X 	int dtr, rts;
-        struct termios old_termios;
-	int cflag;
X 	
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
-	self = (struct irtty_cb *) idev->priv;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRTTY_MAGIC, return;);
-
-	if ( !self->tty)
-		return;
-
-	tty = self->tty;
-	
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
X 	switch (baud) {
X 	case 19200:
-		cflag |= B19200;
X 		dtr = TRUE;
X 		rts = FALSE;
X 		break;
X 	case 115200:
-		cflag |= B115200;
X 		dtr = rts = TRUE;
X 		break;
X 	case 9600:
X 	default:
-		cflag |= B9600;
X 		dtr = FALSE;
X 		rts = TRUE;
X 		break;
X 	}
-	/* Change speed of serial driver */
-	tty->termios->c_cflag = cflag;
-	tty->driver.set_termios(tty, &old_termios);
X 
-	irtty_set_dtr_rts(tty, dtr, rts);
+	/* Change speed of dongle */
+	irda_device_set_dtr_rts(idev, dtr, rts);
X }
X 
-static void esi_reset( struct irda_device *idev, int unused)
+static void esi_reset( struct irda_device *idev)
X {
X 	/* Empty */
X }
@@ -148,14 +123,17 @@
X  *    Init QoS capabilities for the dongle
X  *
X  */
-static void esi_qos_init( struct irda_device *idev, struct qos_info *qos)
+static void esi_qos_init(struct irda_device *idev, struct qos_info *qos)
X {
X 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
X 	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
X }
X 
X #ifdef MODULE
-		
+
+MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
+MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
+
X /*
X  * Function init_module (void)
X  *
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.2.9/linux/drivers/net/irda/girbil.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/irda/girbil.c	Mon Jun  7 16:19:59 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X  * Filename:      girbil.c
- * Version:       1.0
+ * Version:       1.1
X  * Description:   Implementation for the Greenwich GIrBIL dongle
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Feb  6 21:02:33 1999
- * Modified at:   Sat Apr 10 19:53:12 1999
+ * Modified at:   Tue Jun  1 08:47:41 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -28,17 +28,13 @@
X #include <linux/sched.h>
X #include <linux/init.h>
X 
-#include <asm/ioctls.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
X #include <net/irda/irda.h>
X #include <net/irda/irmod.h>
X #include <net/irda/irda_device.h>
X #include <net/irda/irtty.h>
X #include <net/irda/dongle.h>
X 
-static void girbil_reset(struct irda_device *dev, int unused);
+static void girbil_reset(struct irda_device *dev);
X static void girbil_open(struct irda_device *dev, int type);
X static void girbil_close(struct irda_device *dev);
X static void girbil_change_speed(struct irda_device *dev, int baud);
@@ -80,19 +76,19 @@
X 	girbil_init_qos,
X };
X 
-__initfunc(void girbil_init(void))
+__initfunc(int girbil_init(void))
X {
-	irtty_register_dongle(&dongle);
+	return irda_device_register_dongle(&dongle);
X }
X 
X void girbil_cleanup(void)
X {
-	irtty_unregister_dongle(&dongle);
+	irda_device_unregister_dongle(&dongle);
X }
X 
X static void girbil_open(struct irda_device *idev, int type)
X {
-	strcat( idev->description, " <-> girbil");
+	strcat(idev->description, " <-> girbil");
X 
X 	idev->io.dongle_id = type;
X 	idev->flags |= IFF_DONGLE;
@@ -100,8 +96,11 @@
X 	MOD_INC_USE_COUNT;
X }
X 
-static void girbil_close(struct irda_device *dev)
+static void girbil_close(struct irda_device *idev)
X {
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
X 	MOD_DEC_USE_COUNT;
X }
X 
@@ -114,71 +113,42 @@
X  */
X static void girbil_change_speed(struct irda_device *idev, int speed)
X {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
-	struct termios old_termios;
-	int cflag;
X 	__u8 control[2];
X 	
X 	ASSERT(idev != NULL, return;);
X 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
- self = (struct irtty_cb *) idev->priv;
-	
-	ASSERT(self != NULL, return;); 
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
-	if (!self->tty)
-		return;
-
-	tty = self->tty;
-	
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
X 	switch (speed) {
X 	case 9600:
X 	default:
-		cflag |= B9600;
X 		control[0] = GIRBIL_9600;
X 		break;
X 	case 19200:
-		cflag |= B19200;
X 		control[0] = GIRBIL_19200;
X 		break;
X 	case 34800:
-		cflag |= B38400;
X 		control[0] = GIRBIL_38400;
X 		break;
X 	case 57600:
-		cflag |= B57600;
X 		control[0] = GIRBIL_57600;
X 		break;
X 	case 115200:
-		cflag |= B115200;
X 		control[0] = GIRBIL_115200;
X 		break;
X 	}
X 	control[1] = GIRBIL_LOAD;
X 
X 	/* Set DTR and Clear RTS to enter command mode */
-	irtty_set_dtr_rts(tty, FALSE, TRUE);
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
X 
X 	/* Write control bytes */
-	if (tty->driver.write)
-		tty->driver.write(self->tty, 0, control, 2);
+	irda_device_raw_write(idev, control, 2);
X 
X 	current->state = TASK_INTERRUPTIBLE;
X 	schedule_timeout(2);
X 	
X 	/* Go back to normal mode */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
-
-	/* Now change the speed of the serial port */
-	tty->termios->c_cflag = cflag;
-	tty->driver.set_termios(tty, &old_termios);	
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
X }
X 
X /*
@@ -191,46 +161,38 @@
X  *    	  0. set RTS, and wait at least 5 ms 
X  *        1. clear RTS 
X  */
-void girbil_reset(struct irda_device *idev, int unused)
+void girbil_reset(struct irda_device *idev)
X {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
X 	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
X 
X 	ASSERT(idev != NULL, return;);
X 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
- self = (struct irtty_cb *) idev->priv;
-	
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-
-	tty = self->tty;
-	if (!tty)
-		return;
-
X 	/* Reset dongle */
-	irtty_set_dtr_rts(tty, TRUE, FALSE);
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
X 
X 	/* Sleep at least 5 ms */
X 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2);
+	schedule_timeout(MSECS_TO_JIFFIES(20));
X 	
X 	/* Set DTR and clear RTS to enter command mode */
-	irtty_set_dtr_rts(tty, FALSE, TRUE);
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
X 
X 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2);
+	schedule_timeout(MSECS_TO_JIFFIES(20));
X 
X 	/* Write control byte */
-	if (tty->driver.write)
-		tty->driver.write(self->tty, 0, &control, 1);
+	irda_device_raw_write(idev, &control, 1);
X 
X 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2);
+	schedule_timeout(MSECS_TO_JIFFIES(20));
X 
X 	/* Go back to normal mode */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+
+ /* Make sure the IrDA chip also goes to defalt speed */
+	if (idev->change_speed)
+		idev->change_speed(idev, 9600);
X }
X 
X /*
@@ -242,7 +204,7 @@
X static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos)
X {
X 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+	qos->min_turn_time.bits &= 0x03;
X }
X 
X #ifdef MODULE
@@ -258,8 +220,7 @@
X  */
X int init_module(void)
X {
-	girbil_init();
-	return(0);
+	return girbil_init();
X }
X 
X /*
diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.2.9/linux/drivers/net/irda/irport.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/irda/irport.c	Sun Jun 13 10:48:21 1999
@@ -1,43 +1,38 @@
X /*********************************************************************
- *		  
+ * 
X  * Filename:	  irport.c
- * Version:	  0.9
- * Description:   Serial driver for IrDA. 
+ * Version:	  1.0
+ * Description:   Half duplex serial port SIR driver for IrDA. 
X  * Status:	  Experimental.
X  * Author:	  Dag Brattli <da...@cs.uit.no>
X  * Created at:	  Sun Aug  3 13:49:59 1997
- * Modified at:   Sat May 23 23:15:20 1998
+ * Modified at:   Tue Jun  1 10:02:42 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:	  serial.c by Linus Torvalds 
X  * 
- *     Copyright (c) 1997,1998 Dag Brattli <da...@cs.uit.no>
- *     All Rights Reserved.
+ *     Copyright (c) 1997, 1998, 1999 Dag Brattli, All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
X  *     published by the Free Software Foundation; either version 2 of 
X  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- *     NOTICE:
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
X  *
X  *     This driver is ment to be a small half duplex serial driver to be
- *     used for IR-chipsets that has a UART (16550) compatibility mode. If
- *     your chipset is is UART only, you should probably use IrTTY instead
- *     since the Linux serial driver is probably more robust and optimized.
- *
- *     The functions in this file may be used by FIR drivers, but this
- *     driver knows nothing about FIR drivers so don't ever insert such
- *     code into this file. Instead you should code your FIR driver in a
- *     separate file, and then call the functions in this file if
- *     necessary. This is becase it is difficult to use the Linux serial
- *     driver with a FIR driver becase they must share interrupts etc. Most
- *     FIR chipsets can function in advanced SIR mode, and you should
- *     probably use that mode instead of the UART compatibility mode (and
- *     then just forget about this file)
+ *     used for IR-chipsets that has a UART (16550) compatibility mode. 
+ *     Eventually it will replace irtty, because of irtty has some 
+ *     problems that is hard to get around when we don't have control
+ *     over the serial driver. This driver may also be used by FIR 
+ *     drivers to handle SIR mode for them.
X  *
X  ********************************************************************/
X 
@@ -48,14 +43,15 @@
X #include <linux/ioport.h>
X #include <linux/malloc.h>
X #include <linux/string.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
+#include <linux/skbuff.h>
+#include <linux/serial_reg.h>
X #include <linux/errno.h>
X #include <linux/init.h>
X 
-#include <linux/skbuff.h>
-#include <linux/serial_reg.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/spinlock.h>
X 
X #include <net/irda/irda.h>
X #include <net/irda/irmod.h>
@@ -64,105 +60,254 @@
X 
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 06'
echo 'File patch-2.2.10 is continued in part 07'
echo 07 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 09 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 09; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
+	__u8 hcr;
+#endif
+        DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len);
X 
X 	/* Save current set */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
X 
X 	/* Disable DMA */
X 	switch_bank(iobase, SET0);
-	outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
-	
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
-		  DMA_MODE_WRITE);
-	
-	/* idev->media_busy = TRUE; */
-	idev->io.direction = IO_XMIT;
-	
+	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
X 	/* Choose transmit DMA channel  */ 
X 	switch_bank(iobase, SET2);
-	outb(inb(iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL, 
-	     iobase+ADCR1);
+	outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+	save_flags(flags);
+	cli();
+
+	disable_dma(idev->io.dma);
+	clear_dma_ff(idev->io.dma);
+	set_dma_mode(idev->io.dma, DMA_MODE_READ);
+	set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data));
+	set_dma_count(idev->io.dma, idev->tx_buff.len);
+#else
+	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+		  DMA_MODE_WRITE);	
+#endif
+	idev->io.direction = IO_XMIT;
X 	
X 	/* Enable DMA */
X  	switch_bank(iobase, SET0);
-	outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
-	
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+	hcr = inb(iobase+HCR);
+	outb(hcr | HCR_EN_DMA, iobase+HCR);
+	enable_dma(idev->io.dma);
+	restore_flags(flags);
+#else	
+	outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
+#endif
+
X 	/* Restore set register */
X 	outb(set, iobase+SSR);
X }
@@ -577,17 +603,17 @@
X 	int actual = 0;
X __u8 set;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
X 	/* Save current bank */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
X 
-	switch_bank( iobase, SET0);
+	switch_bank(iobase, SET0);
X 	if (!(inb_p(iobase+USR) & USR_TSRE)) {
-		DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+		DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
X 
X 		fifo_size -= 17;
-		DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
X 	}
X 
X 	/* Fill FIFO with current frame */
@@ -597,7 +623,7 @@
X 	}
X         
X 	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	      fifo_size, actual, len);
+	       fifo_size, actual, len);
X 
X 	/* Restore bank */
X 	outb(set, iobase+SSR);
@@ -617,7 +643,7 @@
X 	int iobase;
X 	__u8 set;
X 
-	DEBUG(4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
X 
X 	ASSERT(idev != NULL, return;);
X 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -663,9 +689,10 @@
X  */
X int w83977af_dma_receive(struct irda_device *idev) 
X {
+	struct w83977af_ir *self;
X 	int iobase;
X 	__u8 set;
-#ifdef NETWINDER
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
X 	unsigned long flags;
X 	__u8 hcr;
X #endif
@@ -673,62 +700,60 @@
X 	ASSERT(idev != NULL, return -1;);
X 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
X 
-	DEBUG(0, __FUNCTION__ "\n");
+	DEBUG(4, __FUNCTION__ "\n");
X 
+	self = idev->priv;
X 	iobase= idev->io.iobase;
X 
X 	/* Save current set */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
X 
X 	/* Disable DMA */
-	switch_bank( iobase, SET0);
-	outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+	switch_bank(iobase, SET0);
+	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, SET2);
+	outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,
+	     iobase+ADCR1);
+
+	idev->io.direction = IO_RECV;
+	idev->rx_buff.data = idev->rx_buff.head;
X 
-#ifdef NETWINDER
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
X 	save_flags(flags);
X 	cli();
X 
-	disable_dma( idev->io.dma);
-	clear_dma_ff( idev->io.dma);
-	set_dma_mode( idev->io.dma, DMA_MODE_READ);
-	set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data));
-	set_dma_count( idev->io.dma, idev->rx_buff.truesize);
+	disable_dma(idev->io.dma);
+	clear_dma_ff(idev->io.dma);
+	set_dma_mode(idev->io.dma, DMA_MODE_READ);
+	set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data));
+	set_dma_count(idev->io.dma, idev->rx_buff.truesize);
X #else
-	setup_dma(idev->io.dma, idev->rx_buff.data, 
-		  idev->rx_buff.truesize, DMA_MODE_READ);
+	setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+		  DMA_MODE_READ);
X #endif
-	/* driver->media_busy = FALSE; */
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
-
X 	/* 
X 	 * Reset Rx FIFO. This will also flush the ST_FIFO, it's very 
X 	 * important that we don't reset the Tx FIFO since it might not
X 	 * be finished transmitting yet
X 	 */
-	outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
-	prev.status = 0;
-
-	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
-	switch_bank(iobase, SET2);
-	outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL,
-	     iobase+ADCR1);
+	switch_bank(iobase, SET0);
+	outb(UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
X 	
X 	/* Enable DMA */
X 	switch_bank(iobase, SET0);
-#ifdef NETWINDER
-	hcr = inb( iobase+HCR);
-	enable_dma( idev->io.dma);
-	outb( hcr | HCR_EN_DMA, iobase+HCR);
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+	hcr = inb(iobase+HCR);
+	outb(hcr | HCR_EN_DMA, iobase+HCR);
+	enable_dma(idev->io.dma);
X 	restore_flags(flags);
X #else	
-	outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+	outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
X #endif
-	
X 	/* Restore set */
-	outb( set, iobase+SSR);
-
-	DEBUG( 4, __FUNCTION__ "(), done!\n");	
+	outb(set, iobase+SSR);
X 
X 	return 0;
X }
@@ -742,12 +767,17 @@
X int w83977af_dma_receive_complete(struct irda_device *idev)
X {
X 	struct sk_buff *skb;
+	struct w83977af_ir *self;
+	struct st_fifo *st_fifo;
X 	int len;
X 	int iobase;
X 	__u8 set;
X 	__u8 status;
X 
-	DEBUG(0, __FUNCTION__ "\n");
+	DEBUG(4, __FUNCTION__ "\n");
+
+	self = idev->priv;
+ st_fifo = &self->st_fifo;
X 
X 	iobase = idev->io.iobase;
X 
@@ -756,22 +786,28 @@
X 	
X 	iobase = idev->io.iobase;
X 
+	/* Read status FIFO */
X 	switch_bank(iobase, SET5);
-	if (prev.status & FS_FO_FSFDR) {
-		status = prev.status;
-		len = prev.len;
+	while ((status = inb(iobase+FS_FO)) & FS_FO_FSFDR) {
+		st_fifo->entries[st_fifo->tail].status = status;
X 		
-		prev.status = 0;
-	} else {
-		status = inb(iobase+FS_FO);
-		len = inb(iobase+RFLFL);
-		len |= inb(iobase+RFLFH) << 8;
+		st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);
+		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+		
+		st_fifo->tail++;
+		st_fifo->len++;
X 	}
+	
+	while (st_fifo->len) {
+		/* Get first entry */
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
+		st_fifo->head++;
+		st_fifo->len--;
X 
-	while (status & FS_FO_FSFDR) {
X 		/* Check for errors */
X 		if (status & FS_FO_ERR_MSK) {
-			if ( status & FS_FO_LST_FR) {
+			if (status & FS_FO_LST_FR) {
X 				/* Add number of lost frames to stats */
X 				idev->stats.rx_errors += len;	
X 			} else {
@@ -800,14 +836,20 @@
X 			/* Check if we have transfered all data to memory */
X 			switch_bank(iobase, SET0);
X 			if (inb(iobase+USR) & USR_RDR) {
+#ifdef CONFIG_USE_INTERNAL_TIMER
X 				/* Put this entry back in fifo */
-				prev.status = status;
-				prev.len = len;
-
+				st_fifo->head--;
+				st_fifo->len++;
+				st_fifo->entries[st_fifo->head].status = status;
+				st_fifo->entries[st_fifo->head].len = len;
+				
X 				/* Restore set register */
-				outb( set, iobase+SSR);
+				outb(set, iobase+SSR);
X 			
X 				return FALSE; 	/* I'll be back! */
+#else
+				udelay(80); /* Should be enough!? */
+#endif
X 			}
X 						
X 			skb = dev_alloc_skb(len+1);
@@ -824,28 +866,23 @@
X 			skb_reserve(skb, 1); 
X 			
X 			/* Copy frame without CRC */
-			if ( idev->io.baudrate < 4000000) {
-				skb_put( skb, len-2);
-				memcpy( skb->data, idev->rx_buff.data, len-2);
+			if (idev->io.baudrate < 4000000) {
+				skb_put(skb, len-2);
+				memcpy(skb->data, idev->rx_buff.data, len-2);
X 			} else {
-				skb_put( skb, len-4);
-				memcpy( skb->data, idev->rx_buff.data, len-4);
+				skb_put(skb, len-4);
+				memcpy(skb->data, idev->rx_buff.data, len-4);
X 			}
X 
X 			/* Move to next frame */
X 			idev->rx_buff.data += len;
+			idev->stats.rx_packets++;
X 			
X 			skb->dev = &idev->netdev;
X 			skb->mac.raw  = skb->data;
X 			skb->protocol = htons(ETH_P_IRDA);
-			netif_rx( skb);
-			idev->stats.rx_packets++;
+			netif_rx(skb);
X 		}
-		/* Read next entry in ST_FIFO */
-		switch_bank(iobase, SET5);
-		status = inb( iobase+FS_FO);
-		len = inb( iobase+RFLFL);
-		len |= inb( iobase+RFLFH) << 8;
X 	}
X 	/* Restore set register */
X 	outb(set, iobase+SSR);
@@ -875,7 +912,6 @@
X 	do {
X 		byte = inb(iobase+RBR);
X 		async_unwrap_char(idev, byte);
-
X 	} while (inb(iobase+USR) & USR_RDR); /* Data available */	
X }
X 
@@ -889,9 +925,12 @@
X {
X 	int actual;
X 	__u8 new_icr = 0;
+	__u8 set;
+	int iobase;
X 
X 	DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
X 	
+	iobase = idev->io.iobase;
X 	/* Transmit FIFO low on data */
X 	if (isr & ISR_TXTH_I) {
X 		/* Write data left in transmit buffer */
@@ -899,16 +938,21 @@
X 					    idev->tx_buff.data, 
X 					    idev->tx_buff.len, 
X 					    idev->io.fifo_size);
+
X 		idev->tx_buff.data += actual;
X 		idev->tx_buff.len  -= actual;
X 		
X 		idev->io.direction = IO_XMIT;
X 
X 		/* Check if finished */
-		if (idev->tx_buff.len > 0)
+		if (idev->tx_buff.len > 0) {
X 			new_icr |= ICR_ETXTHI;
-		else { 
-			DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+		} else {
+			set = inb(iobase+SSR);
+			switch_bank(iobase, SET0);
+			outb(AUDR_SFEND, iobase+AUDR);
+			outb(set, iobase+SSR); 
+
X 			idev->netdev.tbusy = 0; /* Unlock */
X 			idev->stats.tx_packets++;
X 
@@ -917,7 +961,6 @@
X 
X 			new_icr |= ICR_ETBREI;
X 		}
-		
X 	}
X 	/* Check if transmission has completed */
X 	if (isr & ISR_TXEMP_I) {
@@ -943,22 +986,20 @@
X  *    Handle MIR/FIR interrupt
X  *
X  */
-static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr)
+static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
X {
X 	__u8 new_icr = 0;
X 	__u8 set;
X 	int iobase;
X 
-	DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr);
-
X 	iobase = idev->io.iobase;
-
X 	set = inb(iobase+SSR);
X 	
X 	/* End of frame detected in FIFO */
X 	if (isr & (ISR_FEND_I|ISR_FSF_I)) {
X 		if (w83977af_dma_receive_complete(idev)) {
X 			
+			/* Wait for next status FIFO interrupt */
X 			new_icr |= ICR_EFSFI;
X 		} else {
X 			/* DMA not finished yet */
@@ -982,7 +1023,7 @@
X 
X 		/* Clear timer event */
X 		/* switch_bank(iobase, SET0); */
-/* 		outb( ASCR_CTE, iobase+ASCR); */
+/* 		outb(ASCR_CTE, iobase+ASCR); */
X 
X 		/* Check if this is a TX timer interrupt */
X 		if (idev->io.direction == IO_XMIT) {
@@ -998,15 +1039,18 @@
X 	}	
X 	/* Finished with DMA */
X 	if (isr & ISR_DMA_I) {
-		w83977af_dma_xmit_complete( idev);
-		
+		w83977af_dma_xmit_complete(idev);
+
X 		/* Check if there are more frames to be transmitted */
-		if (irda_device_txqueue_empty( idev)) {
+		/* if (irda_device_txqueue_empty(idev)) { */
X 		
-			/* Prepare for receive */
-			w83977af_dma_receive(idev);
-			new_icr = ICR_EFSFI;
-		}
+		/* Prepare for receive 
+		 * 
+		 * ** Netwinder Tx DMA likes that we do this anyway **
+		 */
+		w83977af_dma_receive(idev);
+		new_icr = ICR_EFSFI;
+	       /* } */
X 	}
X 	
X 	/* Restore set */
@@ -1030,7 +1074,7 @@
X 
X 	if (idev == NULL) {
X 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
-		       driver_name, irq);
+			driver_name, irq);
X 		return;
X 	}
X 
@@ -1049,7 +1093,7 @@
X 	
X 	if (isr) {
X 		/* Dispatch interrupt handler for the current speed */
-		if ( idev->io.baudrate > 115200)
+		if (idev->io.baudrate > PIO_MAX_SPEED )
X 			icr = w83977af_fir_interrupt(idev, isr);
X 		else
X 			icr = w83977af_sir_interrupt(idev, isr);
@@ -1070,7 +1114,7 @@
X static void w83977af_wait_until_sent(struct irda_device *idev)
X {
X 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(6);
+	schedule_timeout(60*HZ/1000);
X }
X 
X /*
@@ -1085,16 +1129,16 @@
X 	int iobase;
X 	__u8 set;
X 
-	ASSERT( idev != NULL, return FALSE;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	ASSERT(idev != NULL, return FALSE;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
X 
-	if ( idev->io.baudrate > 115200) {
+	if (idev->io.baudrate > 115200) {
X 		iobase = idev->io.iobase;
X 
X 		/* Check if rx FIFO is not empty */
X 		set = inb(iobase+SSR);
-		switch_bank( iobase, SET2);
-		if (( inb( iobase+RXFDTH) & 0x3f) != 0) {
+		switch_bank(iobase, SET2);
+		if ((inb(iobase+RXFDTH) & 0x3f) != 0) {
X 			/* We are receiving something */
X 			status =  TRUE;
X 		}
@@ -1111,12 +1155,12 @@
X  *    
X  *
X  */
-static int w83977af_net_init( struct device *dev)
+static int w83977af_net_init(struct device *dev)
X {
X 	DEBUG(0, __FUNCTION__ "()\n");
X 
X 	/* Set up to be a normal IrDA network device driver */
-	irda_device_setup( dev);
+	irda_device_setup(dev);
X 
X 	/* Insert overrides below this line! */
X 
@@ -1130,7 +1174,7 @@
X  *    Start the device
X  *
X  */
-static int w83977af_net_open( struct device *dev)
+static int w83977af_net_open(struct device *dev)
X {
X 	struct irda_device *idev;
X 	int iobase;
@@ -1147,7 +1191,7 @@
X 	iobase = idev->io.iobase;
X 
X 	if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, 
-			(void *) idev)) {
+			 (void *) idev)) {
X 		return -EAGAIN;
X 	}
X 	/*
@@ -1170,13 +1214,13 @@
X  	/* Enable some interrupts so we can receive frames again */
X  	switch_bank(iobase, SET0);
X  	if (idev->io.baudrate > 115200) {
- 		outb( ICR_EFSFI, iobase+ICR);
- 		w83977af_dma_receive( idev);
+ 		outb(ICR_EFSFI, iobase+ICR);
+ 		w83977af_dma_receive(idev);
X  	} else
- 		outb( ICR_ERBRI, iobase+ICR);
+ 		outb(ICR_ERBRI, iobase+ICR);
X 
X 	/* Restore bank register */
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
X 
X 	MOD_INC_USE_COUNT;
X 
@@ -1195,34 +1239,34 @@
X 	int iobase;
X 	__u8 set;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
X 	
X 	/* Stop device */
X 	dev->tbusy = 1;
X 	dev->start = 0;
X 
-	ASSERT( dev != NULL, return -1;);
+	ASSERT(dev != NULL, return -1;);
X 	idev = (struct irda_device *) dev->priv;
X 	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
X 	
X 	iobase = idev->io.iobase;
X 
-	disable_dma( idev->io.dma);
+	disable_dma(idev->io.dma);
X 
X 	/* Save current set */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
X 	
X 	/* Disable interrupts */
-	switch_bank( iobase, SET0);
-	outb( 0, iobase+ICR); 
+	switch_bank(iobase, SET0);
+	outb(0, iobase+ICR); 
X 
-	free_irq( idev->io.irq, idev);
-	free_dma( idev->io.dma);
+	free_irq(idev->io.irq, idev);
+	free_dma(idev->io.dma);
X 
X 	/* Restore bank register */
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
X 
X 	MOD_DEC_USE_COUNT;
X 
@@ -1230,6 +1274,11 @@
X }
X 
X #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
+MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
X 
X /*
X  * Function init_module (void)
diff -u --recursive --new-file v2.2.9/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.2.9/linux/drivers/net/ni52.c	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/ni52.c	Tue Jun  8 10:27:27 1999
@@ -5,7 +5,7 @@
X  * same Gnu Public License that covers that work.
X  *
X  * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later)
- * Copyrights (c) 1994,1995,1996 by M.Hipp (Michae...@student.uni-tuebingen.de)
+ * Copyrights (c) 1994,1995,1996 by M.Hipp (hi...@informatik.uni-tuebingen.de)
X  *    [feel free to mail ....]
X  *
X  * when using as module: (no autoprobing!)
diff -u --recursive --new-file v2.2.9/linux/drivers/net/ni52.h linux/drivers/net/ni52.h
--- v2.2.9/linux/drivers/net/ni52.h	Thu Apr 11 23:49:38 1996
+++ linux/drivers/net/ni52.h	Tue Jun  8 10:27:27 1999
@@ -4,7 +4,7 @@
X  * This is an extension to the Linux operating system, and is covered by the
X  * same Gnu Public License that covers that work.
X  *
- * copyrights (c) 1994 by Michael Hipp (mh...@student.uni-tuebingen.de)
+ * copyrights (c) 1994 by Michael Hipp (hi...@informatik.uni-tuebingen.de)
X  *
X  * I have done a look in the following sources:
X  *   crynwr-packet-driver by Russ Nelson
diff -u --recursive --new-file v2.2.9/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.2.9/linux/drivers/net/ni65.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/ni65.c	Tue Jun  8 10:27:27 1999
@@ -16,7 +16,7 @@
X  *
X  * comments/bugs/suggestions can be sent to:
X  *   Michael Hipp
- *   email: Michae...@student.uni-tuebingen.de
+ *   email: hi...@informatik.uni-tuebingen.de
X  *
X  * sources:
X  *   some things are from the 'ni6510-packet-driver for dos by Russ Nelson'
@@ -45,6 +45,7 @@
X  */
X 
X /*
+ * 99.Jun.8: added support for /proc/net/dev byte count for xosview (HK)
X  * 96.Sept.29: virt_to_bus stuff added for new memory modell
X  * 96.April.29: Added Harald Koenig's Patches (MH)
X  * 96.April.13: enhanced error handling .. more tests (MH)
@@ -966,8 +967,10 @@
X 				p->stats.tx_errors++;
X 			tmdp->status2 = 0;
X 		}
-		else
+		else {
+			p->stats.tx_bytes -= (short)(tmdp->blen);
X 			p->stats.tx_packets++;
+		}
X 
X #ifdef XMT_VIA_SKB
X 		if(p->tmd_skb[p->tmdlast]) {
@@ -1054,6 +1057,7 @@
X 				eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
X #endif
X 				p->stats.rx_packets++;
+				p->stats.rx_bytes += len;
X 				skb->protocol=eth_type_trans(skb,dev);
X 				netif_rx(skb);
X 			}
diff -u --recursive --new-file v2.2.9/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.2.9/linux/drivers/net/shaper.c	Tue Mar 23 14:35:48 1999
+++ linux/drivers/net/shaper.c	Wed Jun  2 11:29:28 1999
@@ -1,8 +1,8 @@
X /*
X  *			Simple traffic shaper for Linux NET3.
X  *
- *	(c) Copyright 1996 Alan Cox <al...@cymru.net>, All Rights Reserved.
- *				http://www.cymru.net
+ *	(c) Copyright 1996 Alan Cox <al...@redhat.com>, All Rights Reserved.
+ *				http://www.redhat.com
X  *
X  *	This program is free software; you can redistribute it and/or
X  *	modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.2.9/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- v2.2.9/linux/drivers/net/sk_mca.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sk_mca.c	Mon Jun  7 14:34:54 1999
@@ -0,0 +1,1143 @@
+/* 
+net-3-driver for the SKNET MCA-based cards
+
+This is an extension to the Linux operating system, and is covered by the
+same Gnu Public License that covers that work.
+
+Copyright 1999 by Alfred Arnold (alf...@ccac.rwth-aachen.de, aar...@elsa.de)
+
+This driver is based both on the 3C523 driver and the SK_G16 driver.
+
+paper sources:
+  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by 
+  Hans-Peter Messmer for the basic Microchannel stuff
+  
+  'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer
+  for help on Ethernet driver programming
+
+  'Ethernet/IEEE 802.3 Family 1992 World Network Data Book/Handbook' by AMD
+  for documentation on the AM7990 LANCE
+
+  'SKNET Personal Technisches Manual', Version 1.2 by Schneider&Koch
+  for documentation on the Junior board
+
+  'SK-NET MC2+ Technical Manual", Version 1.1 by Schneider&Koch for
+  documentation on the MC2 bord
+  
+  A big thank you to the S&K support for providing me so quickly with
+  documentation!
+
+  Also see http://www.syskonnect.com/
+
+  Missing things:
+
+  -> set debug level via ioctl instead of compile-time switches
+  -> I didn't follow the development of the 2.1.x kernels, so my
+     assumptions about which things changed with which kernel version 
+     are probably nonsense
+
+History:
+  May 16th, 1999
+  	startup
+  May 22st, 1999
+	added private structure, methods
+        begun building data structures in RAM
+  May 23nd, 1999
+	can receive frames, send frames
+  May 24th, 1999
+        modularized intialization of LANCE
+        loadable as module
+	still Tx problem :-(
+  May 26th, 1999
+  	MC2 works
+  	support for multiple devices
+  	display media type for MC2+
+  May 28th, 1999
+	fixed problem in GetLANCE leaving interrupts turned off
+        increase TX queue to 4 packets to improve send performance
+  May 29th, 1999
+	a few corrections in statistics, caught rcvr overruns 
+        reinitialization of LANCE/board in critical situations
+        MCA info implemented
+	implemented LANCE multicast filter
+  Jun 6th, 1999
+	additions for Linux 2.2
+
+ *************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/mca.h>
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#define _SK_MCA_DRIVER_
+#include "sk_mca.h"
+
+/* ------------------------------------------------------------------------
+ * global static data - not more since we can handle multiple boards and
+ * have to pack all state info into the device struct!
+ * ------------------------------------------------------------------------ */
+
+static char *MediaNames[Media_Count]=
+            {"10Base2", "10BaseT", "10Base5", "Unknown"};
+
+static unsigned char poly[] =
+       {1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0,
+        1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0};
+
+/* ------------------------------------------------------------------------
+ * private subfunctions
+ * ------------------------------------------------------------------------ */
+
+/* dump parts of shared memory - only needed during debugging */
+
+#ifdef DEBUG
+static void dumpmem(struct device *dev, u32 start, u32 len)
+{
+  int z;
+
+  for (z = 0; z < len; z++)
+  {
+    if ((z & 15) == 0)
+      printk("%04x:", z);
+    printk(" %02x", readb(dev->mem_start + start + z));
+    if ((z & 15) == 15)
+      printk("\n");
+  }
+}
+
+/* print exact time - ditto */
+
+static void PrTime(void)
+{
+  struct timeval tv;
+
+  do_gettimeofday(&tv);
+  printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec);
+}
+#endif
+
+/* deduce resources out of POS registers */
+
+static void getaddrs(int slot, int junior, int *base, int *irq,
+                     skmca_medium *medium)
+{
+  u_char pos0, pos1, pos2;
+  
+  if (junior)
+  {
+    pos0 = mca_read_stored_pos(slot, 2);
+    *base = ((pos0 & 0x0e) << 13) + 0xc0000;
+    *irq = ((pos0 & 0x10) >> 4) + 10;
+    *medium = Media_Unknown;
+  }
+  else
+  {
+    /* reset POS 104 Bits 0+1 so the shared memory region goes to the
+       configured area between 640K and 1M.  Afterwards, enable the MC2.
+       I really don't know what rode SK to do this... */
+       
+    mca_write_pos(slot, 4, mca_read_stored_pos(slot, 4) & 0xfc);
+    mca_write_pos(slot, 2, mca_read_stored_pos(slot, 2) | 0x01);
+       
+    pos1 = mca_read_stored_pos(slot, 3);
+    pos2 = mca_read_stored_pos(slot, 4);
+    *base = ((pos1 & 0x07) << 14) + 0xc0000;
+    switch (pos2 & 0x0c)
+    {
+      case 0: *irq = 3; break;
+      case 4: *irq = 5; break;
+      case 8: *irq = 10; break;
+      case 12: *irq = 11; break;
+    }
+    *medium = (pos2 >> 6) & 3;
+  }
+}
+
+/* check for both cards:
+   When the MC2 is turned off, it was configured for more than 15MB RAM,
+   is disabled and won't get detected using the standard probe.  We
+   therefore have to scan the slots manually :-( */
+
+static int dofind(int *junior, int firstslot)
+{
+  int slot;
+  unsigned int id;
+
+  for (slot = firstslot; slot < MCA_MAX_SLOT_NR; slot++)
+  {
+    id = mca_read_stored_pos(slot, 0)
+       + (((unsigned int) mca_read_stored_pos(slot, 1)) << 8);
+       
+    *junior = 0;
+    if (id == SKNET_MCA_ID)
+      return slot;
+    *junior = 1;
+    if (id == SKNET_JUNIOR_MCA_ID)
+      return slot;
+  }
+  return MCA_NOTFOUND;
+}
+
+/* reset the whole board */
+
+static void ResetBoard(struct device *dev)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+
+  writeb(CTRL_RESET_ON, priv->ctrladdr);
+  udelay(10);
+  writeb(CTRL_RESET_OFF, priv->ctrladdr);
+}
+
+/* set LANCE register - must be atomic */
+
+static void SetLANCE(struct device *dev, u16 addr, u16 value)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+  unsigned long flags;
+
+  /* disable interrupts */
+
+  save_flags(flags);
+  cli();
+
+  /* wait until no transfer is pending */
+  
+  while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+  /* transfer register address to RAP */
+
+  writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+  writew(addr, priv->ioregaddr);
+  writeb(IOCMD_GO, priv->cmdaddr);
+  udelay(1);
+  while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+  /* transfer data to register */
+
+  writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, priv->ctrladdr);
+  writew(value, priv->ioregaddr);
+  writeb(IOCMD_GO, priv->cmdaddr);
+  udelay(1);
+  while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+  /* reenable interrupts */
+
+  restore_flags(flags);
+}
+
+/* get LANCE register */
+
+static u16 GetLANCE(struct device *dev, u16 addr)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+  unsigned long flags;
+  unsigned int res;
+
+  /* disable interrupts */
+
+  save_flags(flags);
+  cli();
+
+  /* wait until no transfer is pending */
+
+  while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+  /* transfer register address to RAP */
+
+  writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+  writew(addr, priv->ioregaddr);
+  writeb(IOCMD_GO, priv->cmdaddr);
+  udelay(1);
+  while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+  /* transfer data from register */
+
+  writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, priv->ctrladdr);
+  writeb(IOCMD_GO, priv->cmdaddr);
+  udelay(1);
+  while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+  res = readw(priv->ioregaddr);
+
+  /* reenable interrupts */
+
+  restore_flags(flags);
+
+  return res;
+}
+
+/* build up descriptors in shared RAM */
+
+static void InitDscrs(struct device *dev)
+{
+  u32 bufaddr;
+
+  /* Set up Tx descriptors. The board has only 16K RAM so bits 16..23
+     are always 0. */
+
+  bufaddr = RAM_DATABASE;
+  {
+    LANCE_TxDescr descr;
+    int z;
+
+    for (z = 0; z < TXCOUNT; z++)
+    {
+      descr.LowAddr = bufaddr;
+      descr.Flags = 0;
+      descr.Len = 0xf000;
+      descr.Status = 0;
+      memcpy_toio(dev->mem_start + RAM_TXBASE + (z * sizeof(LANCE_TxDescr)),
+                  &descr, sizeof(LANCE_TxDescr));
+      memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
+      bufaddr += RAM_BUFSIZE;
+    }
+  }
+
+  /* do the same for the Rx descriptors */
+ 
+  {
+    LANCE_RxDescr descr;
+    int z;
+
+    for (z = 0; z < RXCOUNT; z++)
+    {
+      descr.LowAddr = bufaddr;
+      descr.Flags = RXDSCR_FLAGS_OWN;
+      descr.MaxLen = -RAM_BUFSIZE;
+      descr.Len = 0;
+      memcpy_toio(dev->mem_start + RAM_RXBASE + (z * sizeof(LANCE_RxDescr)),
+                  &descr, sizeof(LANCE_RxDescr));
+      memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
+      bufaddr += RAM_BUFSIZE;
+    }
+  }
+}
+
+/* calculate the hash bit position for a given multicast address
+   taken more or less directly from the AMD datasheet... */
+
+static void UpdateCRC(unsigned char *CRC, int bit)
+{
+  int j;
+
+  /* shift CRC one bit */
+
+  memmove(CRC + 1, CRC, 32 * sizeof(unsigned char));
+  CRC[0] = 0;
+
+  /* if bit XOR controlbit = 1, set CRC = CRC XOR polynomial */
+
+  if (bit ^ CRC[32])
+    for (j = 0; j < 32; j++)
+      CRC[j] ^= poly[j];
+}
+
+static unsigned int GetHash(char *address)
+{
+  unsigned char CRC[33];
+  int i, byte, hashcode;
+
+  /* a multicast address has bit 0 in the first byte set */
+
+  if ((address[0] & 1) == 0)
+    return -1;
+
+  /* initialize CRC */
+
+  memset(CRC, 1, sizeof(CRC));
+
+  /* loop through address bits */
+
+  for (byte = 0; byte < 6; byte++)
+    for (i = 0; i < 8; i++)
+      UpdateCRC(CRC, (address[byte] >> i) & 1);
+
+  /* hashcode is the 6 least significant bits of the CRC */
+
+  hashcode = 0;
+  for (i = 0; i < 6; i++)
+    hashcode = (hashcode << 1) + CRC[i];
+  return hashcode;
+}
+
+/* feed ready-built initialization block into LANCE */
+
+static void InitLANCE(struct device *dev)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+
+  /* build up descriptors. */
+
+  InitDscrs(dev);
+
+  /* next RX descriptor to be read is the first one.  Since the LANCE
+     will start from the beginning after initialization, we have to 
+     reset out pointers too. */
+
+  priv->nextrx = 0;
+
+  /* no TX descriptors active */
+
+  priv->nexttxput = priv->nexttxdone = priv->txbusy = 0;
+
+  /* set up the LANCE bus control register - constant for SKnet boards */
+
+  SetLANCE(dev, LANCE_CSR3, CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD);
+
+  /* write address of initialization block into LANCE */
+
+  SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff);
+  SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff);
+
+  /* we don't get ready until the LANCE has read the init block */
+
+  dev->tbusy = 1;
+
+  /* let LANCE read the initialization block.  LANCE is ready
+     when we receive the corresponding interrupt. */
+
+  SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT);
+}
+
+/* stop the LANCE so we can reinitialize it */
+
+static void StopLANCE(struct device *dev)
+{
+  /* can't take frames any more */
+
+  dev->tbusy = 1;
+
+  /* disable interrupts, stop it */
+
+  SetLANCE(dev, LANCE_CSR0, CSR0_STOP);
+}
+
+/* initialize card and LANCE for proper operation */
+
+static void InitBoard(struct device *dev)
+{
+  LANCE_InitBlock block;
+
+  /* Lay out the shared RAM - first we create the init block for the LANCE.
+     We do not overwrite it later because we need it again when we switch
+     promiscous mode on/off. */
+
+  block.Mode = 0;
+  if (dev->flags & IFF_PROMISC)
+    block.Mode |= LANCE_INIT_PROM;
+  memcpy(block.PAdr, dev->dev_addr, 6);
+  memset(block.LAdrF, 0, sizeof(block.LAdrF));
+  block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
+  block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
+
+  memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+
+  /* initialize LANCE. Implicitly sets up other structures in RAM. */
+
+  InitLANCE(dev);
+}
+
+/* deinitialize card and LANCE */
+
+static void DeinitBoard(struct device *dev)
+{
+  /* stop LANCE */
+
+  StopLANCE(dev);
+
+  /* reset board */
+
+  ResetBoard(dev);
+}
+
+/* ------------------------------------------------------------------------
+ * interrupt handler(s)
+ * ------------------------------------------------------------------------ */
+
+/* LANCE has read initializazion block -> start it */
+
+static u16 irqstart_handler(struct device *dev, u16 oldcsr0)
+{
+  /* now we're ready to transmit */
+
+  dev->tbusy = 0;
+
+  /* reset IDON bit, start LANCE */
+
+  SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT);
+  return GetLANCE(dev, LANCE_CSR0);
+}
+
+/* receive interrupt */
+
+static u16 irqrx_handler(struct device *dev, u16 oldcsr0)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+  LANCE_RxDescr descr;
+  unsigned int descraddr;
+
+  /* did we loose blocks due to a FIFO overrun ? */
+
+  if (oldcsr0 & CSR0_MISS)
+    priv->stat.rx_fifo_errors++;
+
+  /* run through queue until we reach a descriptor we do not own */
+
+  descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
+  while (1)
+  {
+    /* read descriptor */
+    memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_RxDescr));
+ 
+    /* if we reach a descriptor we do not own, we're done */
+    if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)
+      break;
+
+#ifdef DEBUG
+    PrTime(); printk("Receive packet on descr %d len %d\n", priv->nextrx, descr.Len);
+#endif
+
+    /* erroneous packet ? */
+    if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0)
+    {
+      priv->stat.rx_errors++;
+      if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
+        priv->stat.rx_crc_errors++;
+      else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
+        priv->stat.rx_frame_errors++;
+      else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0)
+        priv->stat.rx_fifo_errors++;
+    }
+
+    /* good packet ? */
+    else
+    {
+      struct sk_buff *skb;
+
+      skb = dev_alloc_skb(descr.Len + 2);
+      if (skb == NULL)
+        priv->stat.rx_dropped++;
+      else
+      {
+        memcpy_fromio(skb_put(skb, descr.Len),
+                      dev->mem_start + descr.LowAddr, descr.Len);
+        skb->dev = dev;
+        skb->protocol = eth_type_trans(skb, dev);
+        skb->ip_summed = CHECKSUM_NONE;
+        priv->stat.rx_packets++;
+#if LINUX_VERSION_CODE >= 0x020119       /* byte counters for >= 2.1.25 */
+        priv->stat.rx_bytes += descr.Len;
+#endif
+        netif_rx(skb);
+      }
+    }
+
+    /* give descriptor back to LANCE */
+    descr.Len = 0;
+    descr.Flags |= RXDSCR_FLAGS_OWN;
+
+    /* update descriptor in shared RAM */
+    memcpy_toio(dev->mem_start + descraddr, &descr, sizeof(LANCE_RxDescr));
+
+    /* go to next descriptor */
+    priv->nextrx++; descraddr += sizeof(LANCE_RxDescr);
+    if (priv->nextrx >= RXCOUNT)
+    {
+      priv->nextrx = 0;
+      descraddr = RAM_RXBASE;
+    }
+  }
+
+  /* reset RINT bit */
+
+  SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT);
+  return GetLANCE(dev, LANCE_CSR0);
+}
+
+/* transmit interrupt */
+
+static u16 irqtx_handler(struct device *dev, u16 oldcsr0)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+  LANCE_TxDescr descr;
+  unsigned int descraddr;
+
+  /* check descriptors at most until no busy one is left */
+
+  descraddr = RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
+  while (priv->txbusy > 0)
+  {
+    /* read descriptor */
+    memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_TxDescr));
+
+    /* if the LANCE still owns this one, we've worked out all sent packets */
+    if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)
+      break;
+
+#ifdef DEBUG
+    PrTime(); printk("Send packet done on descr %d\n", priv->nexttxdone);
+#endif
+
+    /* update statistics */
+    if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0)
+    {
+      priv->stat.tx_packets++;
+#if LINUX_VERSION_CODE >= 0x020119       /* byte counters for >= 2.1.25 */
+      priv->stat.tx_bytes++;
+#endif
+    }
+    else
+    {
+      priv->stat.tx_errors++;
+      if ((descr.Status & TXDSCR_STATUS_UFLO) != 0)
+      {
+        priv->stat.tx_fifo_errors++;
+        InitLANCE(dev);
+      }
+      else if ((descr.Status & TXDSCR_STATUS_LCOL) != 0)
+        priv->stat.tx_window_errors++;
+      else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0)
+        priv->stat.tx_carrier_errors++;
+      else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0)
+        priv->stat.tx_aborted_errors++;
+    }
+
+    /* go to next descriptor */
+    priv->nexttxdone++;
+    descraddr += sizeof(LANCE_TxDescr);
+    if (priv->nexttxdone >= TXCOUNT)
+    {
+      priv->nexttxdone = 0;
+      descraddr = RAM_TXBASE;
+    }
+    priv->txbusy--;
+  }
+
+  /* reset TX interrupt bit */
+
+  SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT);
+  oldcsr0 = GetLANCE(dev, LANCE_CSR0);
+
+  /* at least one descriptor is freed.  Therefore we can accept
+     a new one */
+
+  dev->tbusy = 0;
+
+  /* inform upper layers we're in business again */
+
+  mark_bh(NET_BH);
+
+  return oldcsr0;
+}
+
+/* general interrupt entry */
+
+static void irq_handler(int irq, void *device, struct pt_regs *regs)
+{
+  struct device *dev = (struct device*) device;
+  u16 csr0val;
+
+  /* read CSR0 to get interrupt cause */
+
+  csr0val = GetLANCE(dev, LANCE_CSR0);
+
+  /* in case we're not meant... */
+
+  if ((csr0val & CSR0_INTR) == 0)
+    return;
+
+  dev->interrupt = 1;
+
+  /* loop through the interrupt bits until everything is clear */
+
+  do
+  {
+    if ((csr0val & CSR0_IDON) != 0)
+      csr0val = irqstart_handler(dev, csr0val);
+    if ((csr0val & CSR0_RINT) != 0)
+      csr0val = irqrx_handler(dev, csr0val);
+    if ((csr0val & CSR0_TINT) != 0)
+      csr0val = irqtx_handler(dev, csr0val);
+  }
+  while ((csr0val & CSR0_INTR) != 0);
+
+  dev->interrupt = 0;
+}
+
+/* ------------------------------------------------------------------------
+ * driver methods
+ * ------------------------------------------------------------------------ */
+
+/* MCA info */
+
+static int skmca_getinfo(char *buf, int slot, void *d)
+{
+  int len = 0, i;
+  struct device *dev = (struct device*) d;
+  skmca_priv *priv;
+  
+  /* can't say anything about an uninitialized device... */
+
+  if (dev == NULL)
+    return len;
+  if (dev->priv == NULL)
+    return len;
+  priv = (skmca_priv*) dev->priv;
+
+  /* print info */
+
+  len += sprintf(buf + len, "IRQ: %d\n", priv->realirq);
+  len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
+                 dev->mem_end - 1);
+  len += sprintf(buf + len, "Transceiver: %s\n", MediaNames[priv->medium]);
+  len += sprintf(buf + len, "Device: %s\n", dev->name);
+  len += sprintf(buf + len, "MAC address:");
+  for (i = 0; i < 6; i ++ )
+    len += sprintf( buf+len, " %02x", dev->dev_addr[i] );
+  buf[len++] = '\n';
+  buf[len] = 0;
+
+  return len;
+}
+
+/* open driver.  Means also initialization and start of LANCE */
+
+static int skmca_open(struct device *dev)
+{
+  int result;
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+
+  /* register resources - only necessary for IRQ */
+  result = request_irq(priv->realirq, irq_handler, SA_SHIRQ | SA_SAMPLE_RANDOM,
+                       "sk_mca", dev);
+  if (result != 0)
+  {
+    printk("%s: failed to register irq %d\n", dev->name, dev->irq);
+    return result;
+  }
+  dev->irq = priv->realirq;
+
+  /* set up the card and LANCE */
+  InitBoard(dev);
+
+#ifdef MODULE
+  MOD_INC_USE_COUNT;
+#endif
+
+  return 0;
+}
+
+/* close driver.  Shut down board and free allocated resources */
+
+static int skmca_close(struct device *dev)
+{
+  /* turn off board */
+  DeinitBoard(dev);
+
+  /* release resources */
+  if (dev->irq != 0)
+    free_irq(dev->irq, dev);
+  dev->irq = 0;
+
+#ifdef MODULE
+  MOD_DEC_USE_COUNT;
+#endif
+
+  return 0;
+}
+
+/* transmit a block. */
+
+static int skmca_tx(struct sk_buff *skb, struct device *dev)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+  LANCE_TxDescr descr;
+  unsigned int address;
+  int tmplen, retval = 0;
+  unsigned long flags;
+
+  /* if we get called with a NULL descriptor, the Ethernet layer thinks 
+     our card is stuck an we should reset it.  We'll do this completely: */
+
+  if (skb == NULL)
+  {
+    DeinitBoard(dev);
+    InitBoard(dev);
+    return 0; /* don't try to free the block here ;-) */
+  }
+
+  /* is there space in the Tx queue ? If no, the upper layer gave us a
+     packet in spite of us not being ready and is really in trouble.
+     We'll do the dropping for him: */
+  if (priv->txbusy >= TXCOUNT)
+  {
+    priv->stat.tx_dropped++;
+    retval = -EIO;
+    goto tx_done;
+  }
+
+  /* get TX descriptor */
+  address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
+  memcpy_fromio(&descr, dev->mem_start + address, sizeof(LANCE_TxDescr));
+
+  /* enter packet length as 2s complement - assure minimum length */
+  tmplen = skb->len;
+  if (tmplen < 60)
+    tmplen = 60;
+  descr.Len = 65536 - tmplen;
+
+  /* copy filler into RAM - in case we're filling up... 
+     we're filling a bit more than necessary, but that doesn't harm
+     since the buffer is far larger... */
+  if (tmplen > skb->len)
+  {
+    char *fill = "NetBSD is a nice OS too! ";
+    unsigned int destoffs = 0, l = strlen(fill);
+
+    while (destoffs < tmplen)
+    {
+      memcpy_toio(dev->mem_start + descr.LowAddr + destoffs, fill, l);
+      destoffs += l;
+    }
+  }
+
+  /* do the real data copying */
+  memcpy_toio(dev->mem_start + descr.LowAddr, skb->data, skb->len);
+
+  /* hand descriptor over to LANCE - this is the first and last chunk */
+  descr.Flags = TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP;
+
+#ifdef DEBUG
+  PrTime(); printk("Send packet on descr %d len %d\n", priv->nexttxput, skb->len);
+#endif
+
+  /* one more descriptor busy */
+  save_flags(flags);
+  cli();
+  priv->nexttxput++;
+  if (priv->nexttxput >= TXCOUNT)
+    priv->nexttxput = 0;
+  priv->txbusy++;
+  dev->tbusy = (priv->txbusy >= TXCOUNT);
+
+  /* write descriptor back to RAM */
+  memcpy_toio(dev->mem_start + address, &descr, sizeof(LANCE_TxDescr));
+
+  /* if no descriptors were active, give the LANCE a hint to read it
+     immediately */
+
+  if (priv->txbusy == 0)
+    SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_TDMD);
+
+  restore_flags(flags);
+
+tx_done:
+
+  /* When did that change exactly ? */
+
+#if LINUX_VERSION_CODE >= 0x020200
+  dev_kfree_skb(skb);
+#else
+  dev_kfree_skb(skb, FREE_WRITE);
+#endif
+  return retval;
+}
+
+/* return pointer to Ethernet statistics */
+
+static struct enet_statistics *skmca_stats(struct device *dev)
+{
+  skmca_priv *priv = (skmca_priv*) dev->priv;
+
+  return &(priv->stat);
+}
+
+/* we don't support runtime reconfiguration, since am MCA card can
+   be unambigously identified by its POS registers. */
+
+static int skmca_config(struct device *dev, struct ifmap *map)
+{
+  return 0;
+}
+
+/* switch receiver mode.  We use the LANCE's multicast filter to prefilter
+   multicast addresses. */
+
+static void skmca_set_multicast_list(struct device *dev)
+{
+  LANCE_InitBlock block;
+
+  /* first stop the LANCE... */
+  StopLANCE(dev);
+
+  /* ...then modify the initialization block... */
+  memcpy_fromio(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
+  if (dev->flags & IFF_PROMISC)
+    block.Mode |= LANCE_INIT_PROM;
+  else
+    block.Mode &= ~LANCE_INIT_PROM;
+
+  if (dev->flags & IFF_ALLMULTI)   /* get all multicasts */
+  {
+    memset(block.LAdrF, 8, 0xff);
+  }
+  else                             /* get selected/no multicasts */
+  {
+    struct dev_mc_list *mptr;
+    int code;
+
+    memset(block.LAdrF, 8, 0x00);
+    for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next)
+    {
+      code = GetHash(mptr->dmi_addr);
+      block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);
+    }
+  }
+
+  memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+
+  /* ...then reinit LANCE with the correct flags */
+  InitLANCE(dev);
+}
+
+/* ------------------------------------------------------------------------
+ * hardware check
+ * ------------------------------------------------------------------------ */
+
+#ifdef MODULE
+static int startslot; /* counts through slots when probing multiple devices */
+#else
+#define startslot 0   /* otherwise a dummy, since there is only eth0 in-kern*/
+#endif
+
+int skmca_probe(struct device *dev)
+{
+  int force_detect = 0;
+  int junior, slot, i;
+  int base = 0, irq = 0;
+  skmca_priv *priv;
+  skmca_medium medium;
+
+  /* can't work without an MCA bus ;-) */
+  
+  if (MCA_bus == 0)
+    return ENODEV;
+    
+  /* start address of 1 --> forced detection */
+  
+  if (dev->mem_start == 1)
+    force_detect = 1;
+
+  /* search through slots */
+  
+  if (dev != NULL)
+  {
+    base = dev->mem_start;
+    irq = dev->irq;
+  }
+  slot = dofind(&junior, startslot);
+
+  while (slot != -1)
+  {
+    /* deduce card addresses */
+
+    getaddrs(slot, junior, &base, &irq, &medium);
+
+#if 0
+    /* this should work, but it doesn't with 2.2.9 :-( 
+       somehow 'mca_is_adapter_used()' is missing in kernel syms... */
+#if LINUX_VERSION_CODE >= 0x020200
+    /* slot already in use ? */
+
+    if (mca_is_adapter_used(slot))
+    {
+      slot = dofind(&junior, slot + 1);
+      continue;
+    }
+#endif
+#endif
+
+    /* were we looking for something different ? */
+    
+    if ((dev->irq != 0) || (dev->mem_start != 0))
+    {
+      if ((dev->irq != 0) && (dev->irq != irq))
+      {
+        slot = dofind(&junior, slot + 1);
+        continue;
+      }
+      if ((dev->mem_start != 0) && (dev->mem_start != base))
+      {
+        slot = dofind(&junior, slot + 1);
+        continue;
+      }
+    }
+  
+    /* found something that matches */
+    
+    break;
+  }
+
+  /* nothing found ? */
+  
+  if (slot == -1)
+    return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV;
+    
+  /* make procfs entries */
+    
+  if (junior)
+    mca_set_adapter_name(slot, "SKNET junior MC2 Ethernet Adapter");
+  else
+    mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");
+  mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);
+
+#if LINUX_VERSION_CODE >= 0x020200
+  mca_mark_as_used(slot);
+#endif
+  
+  /* announce success */
+  printk("%s: SKNet %s adapter found in slot %d\n", dev->name, 
+         junior ? "Junior MC2" : "MC2+", slot + 1);
+
+  /* allocate structure */
+  priv = dev->priv = (skmca_priv*) kmalloc(sizeof(skmca_priv), GFP_KERNEL);
+  priv->slot = slot;
+  priv->macbase = base + 0x3fc0;
+  priv->ioregaddr = base + 0x3ff0;
+  priv->ctrladdr = base + 0x3ff2;
+  priv->cmdaddr = base + 0x3ff3;
+  priv->realirq = irq;
+  priv->medium = medium;
+  memset(&(priv->stat), 0, sizeof(struct enet_statistics));
+  
+  /* set base + irq for this device (irq not allocated so far) */
+  dev->irq = 0;
+  dev->mem_start = base;
+  dev->mem_end = base + 0x4000;
+ 
+  /* set methods */
+  dev->open = skmca_open;
+  dev->stop = skmca_close;
+  dev->set_config = skmca_config;
+  dev->hard_start_xmit = skmca_tx;
+  dev->do_ioctl = NULL;
+  dev->get_stats = skmca_stats;
+  dev->set_multicast_list = skmca_set_multicast_list;
+  dev->flags |= IFF_MULTICAST;
+
+  /* generic setup */
+  ether_setup(dev);
+  dev->interrupt = 0;
+  dev->tbusy = 0;
+  dev->start = 0;
+ 
+  /* copy out MAC address */
+  for (i = 0; i < 6; i++)
+    dev->dev_addr[i] = readb(priv->macbase + (i << 1));
+
+  /* print config */
+  printk("%s: IRQ %d, memory %#lx-%#lx, "
+         "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n",
+         dev->name, priv->realirq,  dev->mem_start, dev->mem_end - 1,
+         dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+         dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+  printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]);
+
+  /* reset board */
+
+  ResetBoard(dev);
+
+#ifdef MODULE
+  startslot = slot + 1;
+#endif
+
+  return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * modularization support
+ * ------------------------------------------------------------------------ */
+
+#ifdef MODULE
+
+#define DEVMAX 5
+
+static char NameSpace[8 * DEVMAX];
+static struct device moddevs[DEVMAX] =
+       {{NameSpace +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+        {NameSpace +  8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+        {NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+        {NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+        {NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}};
+
+int irq=0;
+int io=0;
+
+int init_module(void)
+{
+  int z, res;
+
+  startslot = 0;
+  for (z = 0; z < DEVMAX; z++)
+  {
+    strcpy(moddevs[z].name, "     ");
+    res = register_netdev(moddevs + z);
+    if (res != 0)
+      return (z > 0) ? 0 : -EIO;
+  }
+
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  struct device *dev;
+  skmca_priv *priv;
+  int z;
+
+  if (MOD_IN_USE)
+  {
+    printk("cannot unload, module in use\n");
+    return;
+  }
+
+  for (z = 0; z < DEVMAX; z++)
+  {
+    dev = moddevs + z;
+    if (dev->priv != NULL)
+    {
+      priv = (skmca_priv*) dev->priv;
+      DeinitBoard(dev);
+      if (dev->irq != 0)
+        free_irq(dev->irq, dev);
+      dev->irq = 0;
+      unregister_netdev(dev);
+#if LINUX_VERSION_CODE >= 0x020200
+      mca_mark_as_unused(priv->slot);
+#endif
+      mca_set_adapter_procfn(priv->slot, NULL, NULL);
+      kfree_s(dev->priv, sizeof(skmca_priv));
+      dev->priv = NULL;
+    }
+  }
+}
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.9/linux/drivers/net/sk_mca.h linux/drivers/net/sk_mca.h
--- v2.2.9/linux/drivers/net/sk_mca.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sk_mca.h	Mon Jun  7 14:34:54 1999
@@ -0,0 +1,174 @@
+#ifndef _SK_MCA_INCLUDE_
+#define _SK_MCA_INCLUDE_
+
+#ifdef _SK_MCA_DRIVER_
+
+/* Adapter ID's */
+#define SKNET_MCA_ID 0x6afd
+#define SKNET_JUNIOR_MCA_ID 0x6be9
+
+/* media enumeration - defined in a way that it fits onto the MC2+'s
+   POS registers... */
+   
+typedef enum {Media_10Base2, Media_10BaseT,
+              Media_10Base5, Media_Unknown, Media_Count} skmca_medium;
+
+/* private structure */
+typedef struct
+        {
+          unsigned int slot;       /* MCA-Slot-#                       */
+          unsigned int macbase;    /* base address of MAC address PROM */
+          unsigned int ioregaddr;  /* address of I/O-register (Lo)     */
+          unsigned int ctrladdr;   /* address of control/stat register */
+          unsigned int cmdaddr;    /* address of I/O-command register  */
+          int nextrx;              /* index of next RX descriptor to
+                                      be read                          */
+          int nexttxput;           /* index of next free TX descriptor */
+          int nexttxdone;          /* index of next TX descriptor to 
+                                      be finished                      */
+          int txbusy;              /* # of busy TX descriptors         */
+          struct enet_statistics stat; /* packet statistics            */
+          int realirq;             /* memorizes actual IRQ, even when 
+                                      currently not allocated          */
+          skmca_medium medium;     /* physical cannector               */
+        } skmca_priv;
+
+/* card registers: control/status register bits */
+
+#define CTRL_ADR_DATA      0      /* Bit 0 = 0 ->access data register  */
+#define CTRL_ADR_RAP       1      /* Bit 0 = 1 ->access RAP register   */
+#define CTRL_RW_WRITE      0      /* Bit 1 = 0 ->write register        */
+#define CTRL_RW_READ       2      /* Bit 1 = 1 ->read register         */
+#define CTRL_RESET_ON      0      /* Bit 3 = 0 ->reset board           */
+#define CTRL_RESET_OFF     8      /* Bit 3 = 1 ->no reset of board     */
+
+#define STAT_ADR_DATA      0      /* Bit 0 of ctrl register read back  */
+#define STAT_ADR_RAP       1
+#define STAT_RW_WRITE      0      /* Bit 1 of ctrl register read back  */
+#define STAT_RW_READ       2
+#define STAT_RESET_ON      0      /* Bit 3 of ctrl register read back  */
+#define STAT_RESET_OFF     8
+#define STAT_IRQ_ACT       0      /* interrupt pending                 */
+#define STAT_IRQ_NOACT     16     /* no interrupt pending              */
+#define STAT_IO_NOBUSY     0      /* no transfer busy                  */
+#define STAT_IO_BUSY       32     /* transfer busy                     */
+
+/* I/O command register bits */
+
+#define IOCMD_GO           128    /* Bit 7 = 1 -> start register xfer  */
+
+/* LANCE registers */
+
+#define LANCE_CSR0         0      /* Status/Control                    */
+
+#define CSR0_ERR           0x8000 /* general error flag                */
+#define CSR0_BABL          0x4000 /* transmitter timeout               */
+#define CSR0_CERR          0x2000 /* collision error                   */
+#define CSR0_MISS          0x1000 /* lost Rx block                     */
+#define CSR0_MERR          0x0800 /* memory access error               */
+#define CSR0_RINT          0x0400 /* receiver interrupt                */
+#define CSR0_TINT          0x0200 /* transmitter interrupt             */
+#define CSR0_IDON          0x0100 /* initialization done               */
+#define CSR0_INTR          0x0080 /* general interrupt flag            */
+#define CSR0_INEA          0x0040 /* interrupt enable                  */
+#define CSR0_RXON          0x0020 /* receiver enabled                  */
+#define CSR0_TXON          0x0010 /* transmitter enabled               */
+#define CSR0_TDMD          0x0008 /* force transmission now            */
+#define CSR0_STOP          0x0004 /* stop LANCE                        */
+#define CSR0_STRT          0x0002 /* start LANCE                       */
+#define CSR0_INIT          0x0001 /* read initialization block         */          
+
+#define LANCE_CSR1         1      /* addr bit 0..15 of initialization  */
+#define LANCE_CSR2         2      /*          16..23 block             */
+
+#define LANCE_CSR3         3      /* Bus control                       */
+#define CSR3_BCON_HOLD     0      /* Bit 0 = 0 -> BM1,BM0,HOLD         */
+#define CSR3_BCON_BUSRQ    1      /* Bit 0 = 1 -> BUSAK0,BYTE,BUSRQ    */
+#define CSR3_ALE_HIGH      0      /* Bit 1 = 0 -> ALE asserted high    */
+#define CSR3_ALE_LOW       2      /* Bit 1 = 1 -> ALE asserted low     */
+#define CSR3_BSWAP_OFF     0      /* Bit 2 = 0 -> no byte swap         */
+#define CSR3_BSWAP_ON      0      /* Bit 2 = 1 -> byte swap            */
+
+/* LANCE structures */
+
+typedef struct                    /* LANCE initialization block        */
+        {
+          u16 Mode;               /* mode flags                        */
+          u8  PAdr[6];            /* MAC address                       */
+          u8  LAdrF[8];           /* Multicast filter                  */
+          u32 RdrP;               /* Receive descriptor                */
+          u32 TdrP;               /* Transmit descriptor               */
+        } LANCE_InitBlock;
+        
+/* Mode flags init block */
+
+#define LANCE_INIT_PROM    0x8000 /* enable promiscous mode            */
+#define LANCE_INIT_INTL    0x0040 /* internal loopback                 */
+#define LANCE_INIT_DRTY    0x0020 /* disable retry                     */
+#define LANCE_INIT_COLL    0x0010 /* force collision                   */
+#define LANCE_INIT_DTCR    0x0008 /* disable transmit CRC              */
+#define LANCE_INIT_LOOP    0x0004 /* loopback                          */
+#define LANCE_INIT_DTX     0x0002 /* disable transmitter               */
+#define LANCE_INIT_DRX     0x0001 /* disable receiver                  */
+
+typedef struct                    /* LANCE Tx descriptor               */
+        {
+          u16 LowAddr;            /* bit 0..15 of address              */
+          u16 Flags;              /* bit 16..23 of address + Flags     */
+          u16 Len;                /* 2s complement of packet length    */
+          u16 Status;             /* Result of transmission            */
+        } LANCE_TxDescr;
+
+#define TXDSCR_FLAGS_OWN   0x8000 /* LANCE owns descriptor             */
+#define TXDSCR_FLAGS_ERR   0x4000 /* summary error flag                */
+#define TXDSCR_FLAGS_MORE  0x1000 /* more than one retry needed?       */
+#define TXDSCR_FLAGS_ONE   0x0800 /* one retry?                        */
+#define TXDSCR_FLAGS_DEF   0x0400 /* transmission deferred?            */
+#define TXDSCR_FLAGS_STP   0x0200 /* first packet in chain?            */
+#define TXDSCR_FLAGS_ENP   0x0100 /* last packet in chain?             */
+
+#define TXDSCR_STATUS_BUFF 0x8000 /* buffer error?                     */
+#define TXDSCR_STATUS_UFLO 0x4000 /* silo underflow during transmit?   */
+#define TXDSCR_STATUS_LCOL 0x1000 /* late collision?                   */
+#define TXDSCR_STATUS_LCAR 0x0800 /* loss of carrier?                  */
+#define TXDSCR_STATUS_RTRY 0x0400 /* retry error?                      */
+        
+typedef struct                    /* LANCE Rx descriptor               */
+        {
+          u16 LowAddr;            /* bit 0..15 of address              */
+          u16 Flags;              /* bit 16..23 of address + Flags     */
+          u16 MaxLen;             /* 2s complement of buffer length    */
+          u16 Len;                /* packet length                     */
+        } LANCE_RxDescr;
+
+#define RXDSCR_FLAGS_OWN   0x8000 /* LANCE owns descriptor             */
+#define RXDSCR_FLAGS_ERR   0x4000 /* summary error flag                */
+#define RXDSCR_FLAGS_FRAM  0x2000 /* framing error flag                */
+#define RXDSCR_FLAGS_OFLO  0x1000 /* FIFO overflow?                    */
+#define RXDSCR_FLAGS_CRC   0x0800 /* CRC error?                        */
+#define RXDSCR_FLAGS_BUFF  0x0400 /* buffer error?                     */
+#define RXDSCR_FLAGS_STP   0x0200 /* first packet in chain?            */
+#define RXDCSR_FLAGS_ENP   0x0100 /* last packet in chain?             */
+
+/* RAM layout */
+
+#define TXCOUNT            4      /* length of TX descriptor queue     */
+#define LTXCOUNT           2      /* log2 of it                        */
+#define RXCOUNT            4      /* length of RX descriptor queue     */
+#define LRXCOUNT           2      /* log2 of it                        */
+
+#define RAM_INITBASE       0      /* LANCE init block                  */
+#define RAM_TXBASE         24     /* Start of TX descriptor queue      */
+#define RAM_RXBASE         \
+(RAM_TXBASE + (TXCOUNT * 8))      /* Start of RX descriptor queue      */
+#define RAM_DATABASE       \
+(RAM_RXBASE + (RXCOUNT * 8))      /* Start of data area for frames     */
+#define RAM_BUFSIZE        1580   /* max. frame size - should never be
+                                     reached                           */
+
+#endif /* _SK_MCA_DRIVER_ */
+
+extern int skmca_probe(struct device *);
+
+
+#endif /* _SK_MCA_INCLUDE_ */
\ No newline at end of file
diff -u --recursive --new-file v2.2.9/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.2.9/linux/drivers/net/smc-ultra.c	Wed Mar 10 15:29:46 1999
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 09'
echo 'File patch-2.2.10 is continued in part 10'
echo 10 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 12 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 12; 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
X  * Wait for DMA from host memory to data FIFO to complete, then disable
X  * DMA and wait for it to acknowledge that it's off.
X  */
+if ((p->features & AHC_CMD_CHAN) == 0) {
X dma_finish:
X 	test	DFSTATUS,HDONE	jz dma_finish;
X 	/* Turn off DMA */
X 	and	DFCNTRL, ~HDMAEN;
X 	test	DFCNTRL, HDMAEN jnz .;
X 	ret;
+}
X 
X add_scb_to_free_list:
X 	if ((p->flags & AHC_PAGESCBS) != 0) {
@@ -1433,8 +1464,7 @@
X 	mvi	DMAPARAMS, FIFORESET;
X 	mov	SCB_TAG		call dma_scb;
X unlink_disc_scb:
-	/* jmp instead of call since we want to return anyway */
-	mov	SCBPTR	jmp rem_scb_from_disc_list;
+	mov	DISCONNECTED_SCBH, SCB_NEXT ret;
X dequeue_free_scb:
X 	mov	SCBPTR, FREE_SCBH;
X 	mov	FREE_SCBH, SCB_NEXT ret;
@@ -1446,10 +1476,5 @@
X  * candidates for paging out an SCB if one is needed for a new command.
X  * Modifying the disconnected list is a critical(pause dissabled) section.
X  */
-	mvi	SCB_PREV, SCB_LIST_NULL;
X 	mov	SCB_NEXT, DISCONNECTED_SCBH;
-	mov	DISCONNECTED_SCBH, SCBPTR;
-	cmp	SCB_NEXT,SCB_LIST_NULL je return;
-	mov	SCBPTR,SCB_NEXT;
-	mov	SCB_PREV,DISCONNECTED_SCBH;
-	mov	SCBPTR,DISCONNECTED_SCBH ret;
+	mov	DISCONNECTED_SCBH, SCBPTR ret;
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/aic7xxx/scsi_message.h linux/drivers/scsi/aic7xxx/scsi_message.h
--- v2.2.9/linux/drivers/scsi/aic7xxx/scsi_message.h	Tue Apr 14 14:29:21 1998
+++ linux/drivers/scsi/aic7xxx/scsi_message.h	Wed Jun  9 16:59:34 1999
@@ -38,4 +38,12 @@
X #define MSG_EXT_WDTR_LEN	0x02
X #define MSG_EXT_WDTR_BUS_8_BIT	0x00
X #define MSG_EXT_WDTR_BUS_16_BIT	0x01
-#define MSG_EXT_WDTR_BUS_32_BIT	0x02 
+#define MSG_EXT_WDTR_BUS_32_BIT	0x02
+
+#define MSG_EXT_PPR     0x04
+#define MSG_EXT_PPR_LEN	0x06
+#define MSG_EXT_PPR_OPTION_ST 0x00
+#define MSG_EXT_PPR_OPTION_DT_CRC 0x02
+#define MSG_EXT_PPR_OPTION_DT_UNITS 0x03
+#define MSG_EXT_PPR_OPTION_DT_CRC_QUICK 0x04
+#define MSG_EXT_PPR_OPTION_DT_UNITS_QUICK 0x05
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.2.9/linux/drivers/scsi/aic7xxx.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/aic7xxx.c	Wed Jun  9 16:59:34 1999
@@ -171,91 +171,6 @@
X  */
X 
X /*
- * AIC7XXX_FAKE_NEGOTIATION_CMDS
- *   We now have two distinctly different methods of device negotiation
- *   in this code.  The two methods are selected by either defining or not
- *   defining this option.  The difference is as follows:
- *
- *   With AIC7XXX_FAKE_NEGOTIATION_CMDS not set (commented out)
- *     When the driver is in need of issuing a negotiation command for any
- *     given device, it will add the negotiation message on to part of a
- *     regular SCSI command for the device.  In the process, if the device
- *     is configured for and using tagged queueing, then the code will
- *     also issue that single command as a non-tagged command, attach the
- *     negotiation message to that one command, and use a temporary
- *     queue depth of one to keep the untagged and tagged commands from
- *     overlapping.
- *       Pros: This doesn't use any extra SCB structures, it's simple, it
- *         works most of the time (if not all of the time now), and
- *         since we get the device capability info frmo the INQUIRY data
- *         now, shouldn't cause any problems.
- *       Cons: When we need to send a negotiation command to a device, we
- *         must use a command that is being sent to LUN 0 of the device.
- *         If we try sending one to high LUN numbers, then some devices
- *         get noticeably upset.  Since we have to wait for a command with
- *         LUN == 0 to come along, we may not be able to renegotiate when
- *         we want if the user is actually using say LUN 1 of a CD Changer
- *         instead of using LUN 0 for an extended period of time.
- *
- *   With AIC7XXX_FAKE_NEGOTIATION_CMDS defined
- *     When we need to negotiate with a device, instead of attaching our
- *     negotiation message to an existing command, we insert our own
- *     fictional Scsi_Cmnd into the chain that has the negotiation message
- *     attached to it.  We send this one command as untagged regardless
- *     of the device type, and we fiddle with the queue depth the same as
- *     we would with the option unset to avoid overlapping commands.  The
- *     primary difference between this and the unset option is that the
- *     negotiation message is no longer attached to a specific command,
- *     instead it is its own command and is merely triggered by a
- *     combination of both A) We need to negotiate and B) The mid level
- *     SCSI code has sent us a command.  We still don't do any negotiation
- *     unless there is a valid SCSI command to be processed.
- *       Pros: This fixes the problem above in the Cons section.  Since we
- *         issue our own fake command, we can set the LUN to 0 regardless
- *         of what the LUN is in the real command.  It also means that if
- *         the device get's nasty over negotiation issues, it won't be
- *         showing up on a regular command, so we won't get any SENSE buffer
- *         data or STATUS_BYTE returns to the mid level code that are caused
- *         by snits in the negotiation code.
- *       Cons: We add more code, and more complexity.  This means more ways
- *         in which things could break.  It means a larger driver.  It means
- *         more resource consumption for the fake commands.  However, the
- *         biggest problem is this.  Take a system where there is a CD-ROM
- *         on the SCSI bus.  Someone has a CD in the CD-ROM and is using it.
- *         For some reason the SCSI bus gets reset.  We don't touch the
- *         CD-ROM again for quite a period of time (so we don't renegotiate
- *         after the reset until we do touch the CD-ROM again).  In the
- *         time while we aren't using the CD-ROM, the current disc is
- *         removed and a new one put in.  When we go to check that disc, we
- *         will first have to renegotiate.  In so doing, we issue our fake
- *         SCSI command, which happens to be TEST_UNIT_READY.  The CD-ROM
- *         negotiates with us, then responds to our fake command with a
- *         CHECK_CONDITION status.  We REQUEST_SENSE from the CD-ROM, it
- *         then sends the SENSE data to our fake command to tell it that
- *         it has been through a disc change.  There, now we've cleared out
- *         the SENSE data along with our negotiation command, and when the
- *         real command executes, it won't pick up that the CD was changed.
- *         That's the biggest Con to this approach.  In the future, I could
- *         probably code around this problem though, so this option is still
- *         viable.
- *
- *  So, which command style should you use?  I would appreciate it if people
- *  could try out both types.  I want to know about any cases where one
- *  method works and the other doesn't.  If one method works on significantly
- *  more systems than another, then it will become the default.  If the second
- *  option turns out to work best, then I'll find a way to work around that
- *  big con I listed.
- *
- *  -- July 7, 02:33
- *    OK...I just added some code that should make the Con listed for the
- *    fake commands a non issue now.  However, it needs testing.  For now,
- *    I'm going to make the default to use the fake commands, we'll see how
- *    it goes.
- */
- 
-#define AIC7XXX_FAKE_NEGOTIATION_CMDS
-
-/*
X  * AIC7XXX_STRICT_PCI_SETUP
X  *   Should we assume the PCI config options on our controllers are set with
X  *   sane and proper values, or should we be anal about our PCI config
@@ -336,6 +251,7 @@
X #include "aic7xxx/sequencer.h"
X #include "aic7xxx/scsi_message.h"
X #include "aic7xxx_reg.h"
+#include <scsi/scsicam.h>
X 
X #include <linux/stat.h>
X #include <linux/malloc.h>        /* for kmalloc() */
@@ -354,7 +270,7 @@
X     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
X };
X 
-#define AIC7XXX_C_VERSION  "5.1.10"
+#define AIC7XXX_C_VERSION  "5.1.17"
X 
X #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
X #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -447,10 +363,10 @@
X  * You can try raising me if tagged queueing is enabled, or lowering
X  * me if you only have 4 SCBs.
X  */
-#ifdef CONFIG_AIC7XXX_CMDS_PER_LUN
-#define AIC7XXX_CMDS_PER_LUN CONFIG_AIC7XXX_CMDS_PER_LUN
+#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE
+#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE
X #else
-#define AIC7XXX_CMDS_PER_LUN 24
+#define AIC7XXX_CMDS_PER_DEVICE 8
X #endif
X 
X /* Set this to the delay in seconds after SCSI bus reset. */
@@ -495,7 +411,7 @@
X  *
X  * *** Determining commands per LUN ***
X  * 
- * When AIC7XXX_CMDS_PER_LUN is not defined, the driver will use its
+ * When AIC7XXX_CMDS_PER_DEVICE is not defined, the driver will use its
X  * own algorithm to determine the commands/LUN.  If SCB paging is
X  * enabled, which is always now, the default is 8 commands per lun
X  * that indicates it supports tagged queueing.  All non-tagged devices
@@ -513,8 +429,13 @@
X  * Make a define that will tell the driver not to use tagged queueing
X  * by default.
X  */
+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+#define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\
+                              0, 0, 0, 0, 0, 0, 0, 0}
+#else
X #define DEFAULT_TAG_COMMANDS {255, 255, 255, 255, 255, 255, 255, 255,\
X                               255, 255, 255, 255, 255, 255, 255, 255}
+#endif
X 
X /*
X  * Modify this as you see fit for your system.  By setting tag_commands
@@ -553,6 +474,27 @@
X };
X */
X 
+static adapter_tag_info_t aic7xxx_tag_info[] =
+{
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS},
+  {DEFAULT_TAG_COMMANDS}
+};
+
+
X /*
X  * Define an array of board names that can be indexed by aha_type.
X  * Don't forget to change this when changing the types!
@@ -579,11 +521,14 @@
X   "Adaptec AHA-2944 Ultra SCSI host adapter",           /* AIC_7884 */
X   "Adaptec AIC-7895 Ultra SCSI host adapter",           /* AIC_7895 */
X   "Adaptec AIC-7890/1 Ultra2 SCSI host adapter",        /* AIC_7890 */
+  "Adaptec AHA-293X Ultra2 SCSI host adapter",          /* AIC_7890 */
X   "Adaptec AHA-294X Ultra2 SCSI host adapter",          /* AIC_7890 */
X   "Adaptec AIC-7896/7 Ultra2 SCSI host adapter",        /* AIC_7896 */
X   "Adaptec AHA-394X Ultra2 SCSI host adapter",          /* AIC_7897 */
X   "Adaptec AHA-395X Ultra2 SCSI host adapter",          /* AIC_7897 */
X   "Adaptec PCMCIA SCSI controller",                     /* card bus stuff */
+  "Adaptec AIC-7892 Ultra 160/m SCSI host adapter",     /* AIC_7892 */
+  "Adaptec AIC-7899 Ultra 160/m SCSI host adapter",     /* AIC_7899 */
X };
X 
X /*
@@ -851,15 +796,17 @@
X         SCB_DEVICE_RESET        = 0x0020,
X         SCB_RESET               = 0x0040,
X         SCB_RECOVERY_SCB        = 0x0080,
-        SCB_WAS_BUSY            = 0x0100,
+        SCB_MSGOUT_PPR          = 0x0100,
X         SCB_MSGOUT_SENT         = 0x0200,
X         SCB_MSGOUT_SDTR         = 0x0400,
X         SCB_MSGOUT_WDTR         = 0x0800,
-        SCB_MSGOUT_BITS         = SCB_MSGOUT_SENT | 
+        SCB_MSGOUT_BITS         = SCB_MSGOUT_PPR |
+                                  SCB_MSGOUT_SENT | 
X                                   SCB_MSGOUT_SDTR |
X                                   SCB_MSGOUT_WDTR,
X         SCB_QUEUED_ABORT        = 0x1000,
-        SCB_QUEUED_FOR_DONE     = 0x2000
+        SCB_QUEUED_FOR_DONE     = 0x2000,
+        SCB_WAS_BUSY            = 0x4000
X } scb_flag_type;
X 
X typedef enum {
@@ -913,6 +860,8 @@
X   AHC_AIC7890          = 0x0006,
X   AHC_AIC7895          = 0x0007,
X   AHC_AIC7896          = 0x0008,
+  AHC_AIC7892          = 0x0009,
+  AHC_AIC7899          = 0x000a,
X   AHC_VL               = 0x0100,
X   AHC_EISA             = 0x0200,
X   AHC_PCI              = 0x0400,
@@ -929,6 +878,7 @@
X   AHC_QUEUE_REGS       = 0x0040,
X   AHC_SG_PRELOAD       = 0x0080,
X   AHC_SPIOCAP          = 0x0100,
+  AHC_ULTRA3           = 0x0200,
X   AHC_AIC7770_FE       = AHC_FENONE,
X   AHC_AIC7850_FE       = AHC_SPIOCAP,
X   AHC_AIC7860_FE       = AHC_ULTRA|AHC_SPIOCAP,
@@ -938,6 +888,8 @@
X                          AHC_QUEUE_REGS|AHC_SG_PRELOAD,
X   AHC_AIC7895_FE       = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA,
X   AHC_AIC7896_FE       = AHC_AIC7890_FE,
+  AHC_AIC7892_FE       = AHC_AIC7890_FE|AHC_ULTRA3,
+  AHC_AIC7899_FE       = AHC_AIC7890_FE|AHC_ULTRA3,
X } ahc_feature;
X 
X struct aic7xxx_scb {
@@ -1014,9 +966,12 @@
X   unsigned char goal_period;
X   unsigned char cur_offset;
X   unsigned char goal_offset;
+  unsigned char cur_options;
+  unsigned char goal_options;
X   unsigned char user_width;
X   unsigned char user_period;
X   unsigned char user_offset;
+  unsigned char user_options;
X } transinfo_type;
X 
X /*
@@ -1045,10 +1000,11 @@
X   unsigned long            isr_count;        /* Interrupt count */
X   unsigned long            spurious_int;
X   scb_data_type           *scb_data;
+  volatile unsigned short  needdv;
+  volatile unsigned short  needppr;
X   volatile unsigned short  needsdtr;
-  volatile unsigned short  sdtr_pending;
X   volatile unsigned short  needwdtr;
-  volatile unsigned short  wdtr_pending;
+  volatile unsigned short  dtr_pending;
X   struct aic7xxx_cmd_queue {
X     Scsi_Cmnd *head;
X     Scsi_Cmnd *tail;
@@ -1071,9 +1027,10 @@
X #define  DEVICE_PRESENT                 0x01
X #define  BUS_DEVICE_RESET_PENDING       0x02
X #define  DEVICE_RESET_DELAY             0x04
-#define  DEVICE_PRINT_SDTR              0x08
-#define  DEVICE_PRINT_WDTR              0x10
+#define  DEVICE_PRINT_DTR               0x08
+#define  DEVICE_PARITY_ERROR            0x10
X #define  DEVICE_WAS_BUSY                0x20
+#define  DEVICE_SCSI_3                  0x40
X #define  DEVICE_SCANNED                 0x80
X   volatile unsigned char   dev_flags[MAX_TARGETS];
X   volatile unsigned char   dev_active_cmds[MAX_TARGETS];
@@ -1090,11 +1047,10 @@
X #endif
X 
X 
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
-  Scsi_Cmnd               *dev_wdtr_cmnd[MAX_TARGETS];
-  Scsi_Cmnd               *dev_sdtr_cmnd[MAX_TARGETS];
-#endif
+  Scsi_Cmnd               *dev_dtr_cmnd[MAX_TARGETS];
X 
+  unsigned int             dev_checksum[MAX_TARGETS];
+  
X   unsigned char            dev_last_queue_full[MAX_TARGETS];
X   unsigned char            dev_last_queue_full_count[MAX_TARGETS];
X   unsigned char            dev_max_queue_depth[MAX_TARGETS];
@@ -1102,7 +1058,7 @@
X   volatile scb_queue_type  delayed_scbs[MAX_TARGETS];
X 
X 
-  unsigned char            msg_buf[9];       /* The message for the target */
+  unsigned char            msg_buf[13];      /* The message for the target */
X   unsigned char            msg_type;
X #define MSG_TYPE_NONE              0x00
X #define MSG_TYPE_INITIATOR_MSGOUT  0x01
@@ -1132,6 +1088,7 @@
X   int                      scsi_id_b;        /* channel B for twin adapters */
X   unsigned int             bios_address;
X   int                      board_name_index;
+  unsigned short           needppr_copy;     /* default config */
X   unsigned short           needsdtr_copy;    /* default config */
X   unsigned short           needwdtr_copy;    /* default config */
X   unsigned short           ultraenb;         /* Ultra mode target list */
@@ -1192,9 +1149,12 @@
X  * Provides a mapping of transfer periods in ns/4 to the proper value to
X  * stick in the SCSIRATE reg to use that transfer rate.
X  */
-#define AHC_SYNCRATE_ULTRA2 0
-#define AHC_SYNCRATE_ULTRA  2
-#define AHC_SYNCRATE_FAST   5
+#define AHC_SYNCRATE_ULTRA3 0
+#define AHC_SYNCRATE_ULTRA2 1
+#define AHC_SYNCRATE_ULTRA  3
+#define AHC_SYNCRATE_FAST   6
+#define AHC_SYNCRATE_CRC 0x40
+#define AHC_SYNCRATE_SE  0x10
X static struct aic7xxx_syncrate {
X   /* Rates in Ultra mode have bit 8 of sxfr set */
X #define                ULTRA_SXFR 0x100
@@ -1203,6 +1163,7 @@
X   unsigned char period;
X   const char *rate[2];
X } aic7xxx_syncrates[] = {
+  { 0x42,  0x000,   9,  {"80.0", "160.0"} },
X   { 0x13,  0x000,  10,  {"40.0", "80.0"} },
X   { 0x14,  0x000,  11,  {"33.0", "66.6"} },
X   { 0x15,  0x100,  12,  {"20.0", "40.0"} },
@@ -1410,35 +1371,6 @@
X 
X #endif
X 
-/*
- * See the comments earlier in the file for what this item is all about
- * If you have more than 4 controllers, you will need to increase the
- * the number of items in the array below.  Additionally, if you don't
- * want to have lilo pass a humongous config line to the aic7xxx driver,
- * then you can get in and manually adjust these instead of leaving them
- * at the default.  Pay attention to the comments earlier in this file
- * concerning this array if you are going to hand modify these values.
- */
-static adapter_tag_info_t aic7xxx_tag_info[] =
-{
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS},
-  {DEFAULT_TAG_COMMANDS}
-};
-
X #define VERBOSE_NORMAL         0x0000
X #define VERBOSE_NEGOTIATION    0x0001
X #define VERBOSE_SEQINT         0x0002
@@ -1920,6 +1852,7 @@
X       aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM);
X       aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM);
X       aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM);
+      udelay(15);
X       break;
X 
X     default:
@@ -2084,28 +2017,101 @@
X  *-F*************************************************************************/
X static struct aic7xxx_syncrate *
X aic7xxx_find_syncrate(struct aic7xxx_host *p, unsigned int *period,
-  unsigned int maxsync)
+  unsigned int maxsync, unsigned char *options)
X {
X   struct aic7xxx_syncrate *syncrate;
+  int done = FALSE;
X 
+  switch(*options)
+  {
+    case MSG_EXT_PPR_OPTION_DT_CRC:
+    case MSG_EXT_PPR_OPTION_DT_UNITS:
+      if(!(p->features & AHC_ULTRA3))
+      {
+        *options = 0;
+        maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2);
+      }
+      break;
+    case MSG_EXT_PPR_OPTION_DT_CRC_QUICK:
+    case MSG_EXT_PPR_OPTION_DT_UNITS_QUICK:
+      if(!(p->features & AHC_ULTRA3))
+      {
+        *options = 0;
+        maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2);
+      }
+      else
+      {
+        /*
+         * we don't support the Quick Arbitration variants of dual edge
+         * clocking.  As it turns out, we want to send back the
+         * same basic option, but without the QA attribute.
+         * We know that we are responding because we would never set
+         * these options ourself, we would only respond to them.
+         */
+        switch(*options)
+        {
+          case MSG_EXT_PPR_OPTION_DT_CRC_QUICK:
+            *options = MSG_EXT_PPR_OPTION_DT_CRC;
+            break;
+          case MSG_EXT_PPR_OPTION_DT_UNITS_QUICK:
+            *options = MSG_EXT_PPR_OPTION_DT_UNITS;
+            break;
+        }
+      }
+      break;
+    default:
+      *options = 0;
+      maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2);
+      break;
+  }
X   syncrate = &aic7xxx_syncrates[maxsync];
X   while ( (syncrate->rate[0] != NULL) &&
X          (!(p->features & AHC_ULTRA2) || syncrate->sxfr_ultra2) )
X   {
-    if ( *period <= syncrate->period )
+    if (*period <= syncrate->period) 
X     {
-      /*
-       * When responding to a target that requests sync, the requested rate
-       * may fall between two rates that we can output, but still be a rate
-       * that we can receive.  Because of this, we want to respond with the
-       * same rate that it sent to us even if the persiod we use to send
-       * data to it is lower.  Only lower the response period if we must.
-       */
-      if(syncrate == &aic7xxx_syncrates[maxsync])
+      switch(*options)
+      {
+        case MSG_EXT_PPR_OPTION_DT_CRC:
+        case MSG_EXT_PPR_OPTION_DT_UNITS:
+          if(!(syncrate->sxfr_ultra2 & AHC_SYNCRATE_CRC))
+          {
+            done = TRUE;
+            /*
+             * oops, we went too low for the CRC/DualEdge signalling, so
+             * clear the options byte
+             */
+            *options = 0;
+            /*
+             * We'll be sending a reply to this packet to set the options
+             * properly, so unilaterally set the period as well.
+             */
+            *period = syncrate->period;
+          }
+          else
+          {
+            done = TRUE;
+            if(syncrate == &aic7xxx_syncrates[maxsync])
+            {
+              *period = syncrate->period;
+            }
+          }
+          break;
+        default:
+          if(!(syncrate->sxfr_ultra2 & AHC_SYNCRATE_CRC))
+          {
+            done = TRUE;
+            if(syncrate == &aic7xxx_syncrates[maxsync])
+            {
+              *period = syncrate->period;
+            }
+          }
+          break;
+      }
+      if(done)
X       {
-        *period = syncrate->period;
+        break;
X       }
-      break;
X     }
X     syncrate++;
X   }
@@ -2115,6 +2121,7 @@
X     /*
X      * Use async transfers for this target
X      */
+    *options = 0;
X     *period = 0;
X     syncrate = NULL;
X   }
@@ -2135,7 +2142,7 @@
X {
X   struct aic7xxx_syncrate *syncrate;
X 
-  if ((p->features & AHC_ULTRA2) != 0)
+  if (p->features & AHC_ULTRA2)
X   {
X     scsirate &= SXFR_ULTRA2;
X   }
@@ -2147,12 +2154,14 @@
X   syncrate = &aic7xxx_syncrates[maxsync];
X   while (syncrate->rate[0] != NULL)
X   {
-    if ((p->features & AHC_ULTRA2) != 0)
+    if (p->features & AHC_ULTRA2)
X     {
X       if (syncrate->sxfr_ultra2 == 0)
X         break;
X       else if (scsirate == syncrate->sxfr_ultra2)
X         return (syncrate->period);
+      else if (scsirate == (syncrate->sxfr_ultra2 & ~AHC_SYNCRATE_CRC))
+        return (syncrate->period);
X     }
X     else if (scsirate == (syncrate->sxfr & ~ULTRA_SXFR))
X     {
@@ -2206,11 +2215,11 @@
X static void
X aic7xxx_set_syncrate(struct aic7xxx_host *p, struct aic7xxx_syncrate *syncrate,
X     int target, int channel, unsigned int period, unsigned int offset,
-    unsigned int type)
+    unsigned char options, unsigned int type)
X {
X   unsigned char tindex;
X   unsigned short target_mask;
-  unsigned char lun;
+  unsigned char lun, old_options;
X   unsigned int old_period, old_offset;
X 
X   tindex = target | (channel << 3);
@@ -2225,6 +2234,7 @@
X 
X   old_period = p->transinfo[tindex].cur_period;
X   old_offset = p->transinfo[tindex].cur_offset;
+  old_options = p->transinfo[tindex].cur_options;
X 
X   
X   if (type & AHC_TRANS_CUR)
@@ -2237,7 +2247,18 @@
X       scsirate &= ~SXFR_ULTRA2;
X       if (syncrate != NULL)
X       {
-        scsirate |= syncrate->sxfr_ultra2;
+        switch(options)
+        {
+          case MSG_EXT_PPR_OPTION_DT_UNITS:
+            /*
+             * mask off the CRC bit in the xfer settings
+             */
+            scsirate |= (syncrate->sxfr_ultra2 & ~AHC_SYNCRATE_CRC);
+            break;
+          default:
+            scsirate |= syncrate->sxfr_ultra2;
+            break;
+        }
X       }
X       if (type & AHC_TRANS_ACTIVE)
X       {
@@ -2278,9 +2299,10 @@
X     aic_outb(p, scsirate, TARG_SCSIRATE + tindex);
X     p->transinfo[tindex].cur_period = period;
X     p->transinfo[tindex].cur_offset = offset;
+    p->transinfo[tindex].cur_options = options;
X     if ( !(type & AHC_TRANS_QUITE) &&
X          (aic7xxx_verbose & VERBOSE_NEGOTIATION) &&
-         (p->dev_flags[tindex] & DEVICE_PRINT_SDTR) )
+         (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
X     {
X       if (offset)
X       {
@@ -2295,7 +2317,7 @@
X         printk(INFO_LEAD "Using asynchronous transfers.\n",
X                p->host_no, channel, target, lun);
X       }
-      p->dev_flags[tindex] &= ~DEVICE_PRINT_SDTR;
+      p->dev_flags[tindex] &= ~DEVICE_PRINT_DTR;
X     }
X   }
X 
@@ -2303,12 +2325,14 @@
X   {
X     p->transinfo[tindex].goal_period = period;
X     p->transinfo[tindex].goal_offset = offset;
+    p->transinfo[tindex].goal_options = options;
X   }
X 
X   if (type & AHC_TRANS_USER)
X   {
X     p->transinfo[tindex].user_period = period;
X     p->transinfo[tindex].user_offset = offset;
+    p->transinfo[tindex].user_options = options;
X   }
X }
X 
@@ -2325,20 +2349,13 @@
X {
X   unsigned char tindex;
X   unsigned short target_mask;
-  unsigned int old_width, new_offset;
+  unsigned int old_width;
X 
X   tindex = target | (channel << 3);
X   target_mask = 1 << tindex;
X   
X   old_width = p->transinfo[tindex].cur_width;
X 
-  if (p->features & AHC_ULTRA2)
-    new_offset = MAX_OFFSET_ULTRA2;
-  else if (width == MSG_EXT_WDTR_BUS_16_BIT)
-    new_offset = MAX_OFFSET_16BIT;
-  else
-    new_offset = MAX_OFFSET_8BIT;
-  
X   if (type & AHC_TRANS_CUR) 
X   {
X     unsigned char scsirate;
@@ -2356,12 +2373,12 @@
X 
X     p->transinfo[tindex].cur_width = width;
X 
-    if ((aic7xxx_verbose & VERBOSE_NEGOTIATION2) && 
-        (p->dev_flags[tindex] & DEVICE_PRINT_WDTR))
+    if ( !(type & AHC_TRANS_QUITE) &&
+          (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && 
+          (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
X     {
X       printk(INFO_LEAD "Using %s transfers\n", p->host_no, channel, target,
X         lun, (scsirate & WIDEXFER) ? "Wide(16bit)" : "Narrow(8bit)" );
-      p->dev_flags[tindex] &= ~DEVICE_PRINT_WDTR;
X     }
X   }
X 
@@ -2370,14 +2387,21 @@
X   if (type & AHC_TRANS_USER)
X     p->transinfo[tindex].user_width = width;
X 
-  /*
-   * Having just set the width, the SDTR should come next, and we need a valid
-   * offset for the SDTR.  So, we make sure we put a valid one in here now as
-   * the goal_offset.
-   */
X   if (p->transinfo[tindex].goal_offset)
-    p->transinfo[tindex].goal_offset = new_offset;
-
+  {
+    if (p->features & AHC_ULTRA2)
+    {
+      p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+    }
+    else if (width == MSG_EXT_WDTR_BUS_16_BIT)
+    {
+      p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+    }
+    else
+    {
+      p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+    }
+  }
X }
X       
X /*+F*************************************************************************
@@ -2543,14 +2567,6 @@
X   if (match != 0)
X     match = ((tag == scb->hscb->tag) || (tag == SCB_LIST_NULL));
X 
-  if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
-  {
-    printk(KERN_INFO "(scsi%d:%d:%d:%d:tag%d) %s search criteria"
-      " (scsi%d:%d:%d:%d:tag%d)\n", p->host_no, CTL_OF_SCB(scb),
-      scb->hscb->tag, (match) ? "matches" : "doesn't match",
-      p->host_no, channel, target, lun, tag);
-  }
-
X   return (match);
X }
X 
@@ -2584,14 +2600,13 @@
X  *   to the free list.
X  *-F*************************************************************************/
X static unsigned char
-aic7xxx_rem_scb_from_disc_list(struct aic7xxx_host *p, unsigned char scbptr)
+aic7xxx_rem_scb_from_disc_list(struct aic7xxx_host *p, unsigned char scbptr,
+                               unsigned char prev)
X {
X   unsigned char next;
-  unsigned char prev;
X 
X   aic_outb(p, scbptr, SCBPTR);
X   next = aic_inb(p, SCB_NEXT);
-  prev = aic_inb(p, SCB_PREV);
X   aic7xxx_add_curscb_to_free_list(p);
X 
X   if (prev != SCB_LIST_NULL)
@@ -2604,11 +2619,6 @@
X     aic_outb(p, next, DISCONNECTED_SCBH);
X   }
X 
-  if (next != SCB_LIST_NULL)
-  {
-    aic_outb(p, next, SCBPTR);
-    aic_outb(p, prev, SCB_PREV);
-  }
X   return next;
X }
X 
@@ -2755,7 +2765,7 @@
X          * Place in the scb array; never is removed
X          */
X         p->scb_data->scb_array[p->scb_data->numscbs++] = scbp;
-        scbq_insert_head(&p->scb_data->free_scbs, scbp);
+        scbq_insert_tail(&p->scb_data->free_scbs, scbp);
X       }
X       scbp->kmalloc_ptr = scb_ap;
X     }
@@ -2796,6 +2806,7 @@
X   Scsi_Cmnd *cmd;
X #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
X   unsigned int cpu_flags = 0;
+#endif
X   
X   DRIVER_LOCK
X   while (p->completeq.head != NULL)
@@ -2803,20 +2814,9 @@
X     cmd = p->completeq.head;
X     p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble;
X     cmd->host_scribble = NULL;
-    sti();
X     cmd->scsi_done(cmd);
-    cli();
X   }
X   DRIVER_UNLOCK
-#else
-  while (p->completeq.head != NULL)
-  {
-    cmd = p->completeq.head;
-    p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble;
-    cmd->host_scribble = NULL;
-    cmd->scsi_done(cmd);
-  }
-#endif
X }
X 
X /*+F*************************************************************************
@@ -2889,16 +2889,13 @@
X       }
X #define WIDE_INQUIRY_BITS 0x60
X #define SYNC_INQUIRY_BITS 0x10
+#define SCSI_VERSION_BITS 0x07
X       if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
X            (p->features & AHC_WIDE) )
X       {
X         p->needwdtr |= (1<<tindex);
X         p->needwdtr_copy |= (1<<tindex);
-        if ( (p->flags & AHC_SEEPROM_FOUND) &&
-             (p->transinfo[tindex].user_width != MSG_EXT_WDTR_BUS_16_BIT) )
-          p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
-        else
-          p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_16_BIT;
+        p->transinfo[tindex].goal_width = p->transinfo[tindex].user_width;
X       }
X       else
X       {
@@ -2916,28 +2913,10 @@
X         p->needsdtr |= (1<<tindex);
X         p->needsdtr_copy |= (1<<tindex);
X 
-        if (p->flags & AHC_SEEPROM_FOUND)
+        p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
+        p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
+        if (p->transinfo[tindex].user_offset)
X         {
-          p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
-          p->transinfo[tindex].goal_offset = p->transinfo[tindex].user_offset;
-        }
-        else
-        {
-          if (p->features & AHC_ULTRA2)
-          {
-            p->transinfo[tindex].goal_period =
-              aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
-          }
-          else if (p->features & AHC_ULTRA)
-          {
-            p->transinfo[tindex].goal_period =
-              aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
-          }
-          else
-          {
-            p->transinfo[tindex].goal_period =
-              aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
-          }
X           if (p->features & AHC_ULTRA2)
X             p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
X           else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
@@ -2952,14 +2931,57 @@
X         p->needsdtr_copy &= ~(1<<tindex);
X         p->transinfo[tindex].goal_period = 0;
X         p->transinfo[tindex].goal_offset = 0;
+        p->transinfo[tindex].goal_options = 0;
+      }
+      if ( (buffer[2] & SCSI_VERSION_BITS) == 3 )
+      {
+        p->dev_flags[tindex] |= DEVICE_SCSI_3;
+        /*
+         * OK, we are a SCSI 3 device and we are in need of negotiation.
+         * Use PPR messages instead of WDTR and SDTR messages.
+         */
+        if ( (p->needsdtr & (1<<tindex)) ||
+             (p->needwdtr & (1<<tindex)) )
+        {
+          p->needppr |= (1<<tindex);
+          p->needppr_copy |= (1<<tindex);
+        }
+        p->needwdtr &= ~(1<<tindex);
+        p->needwdtr_copy &= ~(1<<tindex);
+        p->needsdtr &= ~(1<<tindex);
+        p->needsdtr_copy &= ~(1<<tindex);
+      }
+      /*
+       * Get the INQUIRY checksum.  We use this on Ultra 160/m
+       * and older devices both.  It allows us to drop speed on any bus type
+       * while at the same time giving us the needed domain validation for
+       * Ultra 160/m
+       *
+       * Note: We only get the checksum and set the SCANNED bit if this is
+       * one of our dtr commands.  If we don't do this, then we end up
+       * getting bad checksum results on the mid-level SCSI code's INQUIRY
+       * commands.
+       */
+      if(p->dev_dtr_cmnd[tindex] == cmd) {
+        unsigned int checksum = 0;
+        int *ibuffer;
+        int i=0;
+
+        ibuffer = (int *)buffer;
+        for( i = 0; i < (cmd->request_bufflen >> 2); i++)
+        {
+          checksum += ibuffer[i];
+        }
+        p->dev_checksum[tindex] = checksum;
+        p->dev_flags[tindex] |= DEVICE_SCANNED;
+        p->dev_flags[tindex] |= DEVICE_PRINT_DTR;
X       }
-      p->dev_flags[tindex] |= DEVICE_SCANNED;
-      p->dev_flags[tindex] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR;
X #undef WIDE_INQUIRY_BITS
X #undef SYNC_INQUIRY_BITS
+#undef SCSI_VERSION_BITS
X     }
X   }
-  else if ((scb->flags & (SCB_MSGOUT_WDTR | SCB_MSGOUT_SDTR)) != 0)
+  else if ((scb->flags & SCB_MSGOUT_BITS) != 0)
X   {
X     unsigned short mask;
X     int message_error = FALSE;
@@ -2979,11 +3001,11 @@
X 
X     if (scb->flags & SCB_MSGOUT_WDTR)
X     {
-      p->wdtr_pending &= ~mask;
+      p->dtr_pending &= ~mask;
X       if (message_error)
X       {
X         if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
-             (p->dev_flags[tindex] & DEVICE_PRINT_WDTR) )
+             (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
X         {
X           printk(INFO_LEAD "Device failed to complete Wide Negotiation "
X             "processing and\n", p->host_no, CTL_OF_SCB(scb));
@@ -2991,7 +3013,6 @@
X             "disabling future\n", p->host_no, CTL_OF_SCB(scb));
X           printk(INFO_LEAD "Wide negotiation to this device.\n", p->host_no,
X             CTL_OF_SCB(scb));
-          p->dev_flags[tindex] &= ~DEVICE_PRINT_WDTR;
X         }
X         p->needwdtr &= ~mask;
X         p->needwdtr_copy &= ~mask;
@@ -2999,11 +3020,11 @@
X     }
X     if (scb->flags & SCB_MSGOUT_SDTR)
X     {
-      p->sdtr_pending &= ~mask;
+      p->dtr_pending &= ~mask;
X       if (message_error)
X       {
X         if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
-             (p->dev_flags[tindex] & DEVICE_PRINT_SDTR) )
+             (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
X         {
X           printk(INFO_LEAD "Device failed to complete Sync Negotiation "
X             "processing and\n", p->host_no, CTL_OF_SCB(scb));
@@ -3011,12 +3032,38 @@
X             "disabling future\n", p->host_no, CTL_OF_SCB(scb));
X           printk(INFO_LEAD "Sync negotiation to this device.\n", p->host_no,
X             CTL_OF_SCB(scb));
-          p->dev_flags[tindex] &= ~DEVICE_PRINT_SDTR;
+          p->dev_flags[tindex] &= ~DEVICE_PRINT_DTR;
X         }
X         p->needsdtr &= ~mask;
X         p->needsdtr_copy &= ~mask;
X       }
X     }
+    if (scb->flags & SCB_MSGOUT_PPR)
+    {
+      p->dtr_pending &= ~mask;
+      if(message_error)
+      {
+        if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+             (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
+        {
+          printk(INFO_LEAD "Device failed to complete Parallel Protocol "
+            "Request processing and\n", p->host_no, CTL_OF_SCB(scb));
+          printk(INFO_LEAD "returned a sense error code for invalid message, "
+            "disabling future\n", p->host_no, CTL_OF_SCB(scb));
+          printk(INFO_LEAD "Parallel Protocol Request negotiation to this "
+            "device.\n", p->host_no, CTL_OF_SCB(scb));
+        }
+        /*
+         * Disable PPR negotiation and revert back to WDTR and SDTR setup
+         */
+        p->needppr &= ~mask;
+        p->needppr_copy &= ~mask;
+        p->needsdtr |= mask;
+        p->needsdtr_copy |= mask;
+        p->needwdtr |= mask;
+        p->needwdtr_copy |= mask;
+      }
+    }
X   }
X   queue_depth = p->dev_temp_queue_depth[tindex];
X   if (queue_depth >= p->dev_active_cmds[tindex])
@@ -3058,16 +3105,6 @@
X   p->dev_active_cmds[tindex]--;
X   p->activescbs--;
X 
-  /*
-   * If this was an untagged I/O, unbusy the target so the sequencer won't
-   * mistake things later
-   */
-  if (aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun, FALSE) ==
-      scb->hscb->tag)
-  {
-    aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun, TRUE);
-  }
-
X   {
X     int actual;
X 
@@ -3122,7 +3159,7 @@
X #endif /* AIC7XXX_PROC_STATS */
X       }
X #ifdef AIC7XXX_PROC_STATS
-      x = -10;
+      x = -11;
X       while(actual)
X       {
X         actual >>= 1;
@@ -3429,11 +3466,10 @@
X       if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
X         printk(INFO_LEAD "Cleaning up status information "
X           "and delayed_scbs.\n", p->host_no, channel, i, lun);
-      p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
+      p->dev_flags[i] &= ~(BUS_DEVICE_RESET_PENDING | DEVICE_PARITY_ERROR);
X       if ( tag == SCB_LIST_NULL )
X       {
-        p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR |
-                           DEVICE_RESET_DELAY;
+        p->dev_flags[i] |= DEVICE_PRINT_DTR | DEVICE_RESET_DELAY;
X         p->dev_expires[i] = jiffies + (4 * HZ);
X         p->dev_timer_active |= (0x01 << i);
X         p->dev_last_queue_full_count[i] = 0;
@@ -3625,7 +3661,7 @@
X   if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
X     printk(INFO_LEAD "Cleaning disconnected scbs "
X       "list.\n", p->host_no, channel, target, lun);
-  if (p->features & AHC_PAGESCBS)
+  if (p->flags & AHC_PAGESCBS)
X   {
X     unsigned char next, prev, scb_index;
X 
@@ -3641,14 +3677,14 @@
X         printk(WARN_LEAD "Disconnected List inconsistency; SCB index=%d, "
X           "numscbs=%d\n", p->host_no, channel, target, lun, scb_index,
X           p->scb_data->numscbs);
-        next = aic7xxx_rem_scb_from_disc_list(p, next);
+        next = aic7xxx_rem_scb_from_disc_list(p, next, prev);
X       }
X       else
X       {
X         scbp = p->scb_data->scb_array[scb_index];
X         if (aic7xxx_match_scb(p, scbp, target, channel, lun, tag))
X         {
-          next = aic7xxx_rem_scb_from_disc_list(p, next);
+          next = aic7xxx_rem_scb_from_disc_list(p, next, prev);
X           if (scbp->flags & SCB_WAITINGQ)
X           {
X             p->dev_active_cmds[TARGET_INDEX(scbp->cmd)]++;
@@ -3677,7 +3713,7 @@
X    * Walk the free list making sure no entries on the free list have
X    * a valid SCB_TAG value or SCB_CONTROL byte.
X    */
-  if (p->features & AHC_PAGESCBS)
+  if (p->flags & AHC_PAGESCBS)
X   {
X     unsigned char next;
X 
@@ -3734,7 +3770,6 @@
X     {
X       aic_outb(p, SCB_LIST_NULL, SCB_TAG);
X       aic_outb(p, SCB_LIST_NULL, SCB_NEXT);
-      aic_outb(p, SCB_LIST_NULL, SCB_PREV);
X       aic_outb(p, 0, SCB_CONTROL);
X       aic7xxx_add_curscb_to_free_list(p);
X     }
@@ -3863,28 +3898,35 @@
X   if (channel == 1)
X   {
X     p->needsdtr |= (p->needsdtr_copy & 0xFF00);
-    p->sdtr_pending &= 0x00FF;
+    p->dtr_pending &= 0x00FF;
X     offset_min = 8;
X     offset_max = 16;
X   }
X   else
X   {
-    if (p->features & AHC_WIDE)
+    if (p->features & AHC_TWIN)
X     {
-      p->needsdtr = p->needsdtr_copy;
-      p->needwdtr = p->needwdtr_copy;
-      p->sdtr_pending = 0x0;
-      p->wdtr_pending = 0x0;
+      /* Channel A */
+      p->needsdtr |= (p->needsdtr_copy & 0x00FF);
+      p->dtr_pending &= 0xFF00;
X       offset_min = 0;
-      offset_max = 16;
+      offset_max = 8;
X     }
X     else
X     {
-      /* Channel A */
-      p->needsdtr |= (p->needsdtr_copy & 0x00FF);
-      p->sdtr_pending &= 0xFF00;
+      p->needppr = p->needppr_copy;
+      p->needsdtr = p->needsdtr_copy;
+      p->needwdtr = p->needwdtr_copy;
+      p->dtr_pending = 0x0;
X       offset_min = 0;
-      offset_max = 8;
+      if (p->features & AHC_WIDE)
+      {
+        offset_max = 16;
+      }
+      else
+      {
+        offset_max = 8;
+      }
X     }
X   }
X 
@@ -4188,6 +4230,30 @@
X 
X /*+F*************************************************************************
X  * Function:
+ *   aic7xxx_construct_ppr
+ *
+ * Description:
+ *   Build up a Parallel Protocol Request message for use with SCSI-3
+ *   devices.
+ *-F*************************************************************************/
+static void
+aic7xxx_construct_ppr(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
+{
+  int tindex = TARGET_INDEX(scb->cmd);
+
+  p->msg_buf[p->msg_index++] = MSG_EXTENDED;
+  p->msg_buf[p->msg_index++] = MSG_EXT_PPR_LEN;
+  p->msg_buf[p->msg_index++] = MSG_EXT_PPR;
+  p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_period;
+  p->msg_buf[p->msg_index++] = 0;
+  p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_offset;
+  p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_width;
+  p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_options;
+  p->msg_len += 8;
+}
+
+/*+F*************************************************************************
+ * Function:
X  *   aic7xxx_construct_sdtr
X  *
X  * Description:
@@ -4304,10 +4370,10 @@
X   /*
X    * Go back to async/narrow transfers and renegotiate.
X    */
+  p->needppr |= (p->needppr_copy & targ_mask);
X   p->needsdtr |= (p->needsdtr_copy & targ_mask);
X   p->needwdtr |= (p->needwdtr_copy & targ_mask);
-  p->sdtr_pending &= ~targ_mask;
-  p->wdtr_pending &= ~targ_mask;
+  p->dtr_pending &= ~targ_mask;
X   aic_outb(p, 0, TARG_SCSIRATE + tindex);
X   if (p->features & AHC_ULTRA2)
X     aic_outb(p, 0, TARG_OFFSET + tindex);
@@ -4315,7 +4381,7 @@
X   if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
X     printk(INFO_LEAD "Bus Device Reset delivered.\n", p->host_no, channel,
X       target, -1);
-  aic7xxx_run_done_queue(p, /*complete*/ FALSE);
+  aic7xxx_run_done_queue(p, /*complete*/ TRUE);
X }
X 
X /*+F*************************************************************************
@@ -4360,6 +4426,8 @@
X                p->host_no, channel, target, lun,
X                aic_inb(p, SAVED_TCL), aic_inb(p, ARG_1),
X                (aic_inb(p, SEQADDR1) << 8) | aic_inb(p, SEQADDR0));
+        if (aic7xxx_panic_on_abort)
+          aic7xxx_panic_abort(p, NULL);
X       }
X       break;
X 
@@ -4387,7 +4455,7 @@
X             lun, aic_inb(p, LASTPHASE), aic_inb(p, SAVED_TCL));
X 
X         aic7xxx_reset_channel(p, channel, /*initiate reset*/ TRUE);
-        aic7xxx_run_done_queue(p, FALSE);
+        aic7xxx_run_done_queue(p, TRUE);
X 
X       }
X       break;
@@ -4517,7 +4585,7 @@
X                   aic7xxx_reset_device(p, target, channel, lun, i);
X                   reset++;
X                 }
-                aic7xxx_run_done_queue(p, FALSE);
+                aic7xxx_run_done_queue(p, TRUE);
X               }
X             }
X             aic7xxx_verbose = old_verbose;
@@ -4533,6 +4601,51 @@
X             aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
X           }
X         }
+        else if (scb->flags & SCB_MSGOUT_PPR)
+        {
+          /*
+           * As per the draft specs, any device capable of supporting any of
+           * the option values other than 0 are not allowed to reject the
+           * PPR message.  Instead, they must negotiate out what they do
+           * support instead of rejecting our offering.
+           */
+          p->needppr &= ~target_mask;
+          p->needppr_copy &= ~target_mask;
+          aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT,
+            (AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE));
+          aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
+                               AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
+          p->transinfo[tindex].goal_options = 0;
+          p->dtr_pending &= ~target_mask;
+          scb->flags &= ~SCB_MSGOUT_BITS;
+          if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Device is rejecting PPR messages, falling "
+              "back.\n", p->host_no, channel, target, lun);
+          }
+          if ( p->transinfo[tindex].goal_width )
+          {
+            p->needwdtr |= target_mask;
+            p->needwdtr_copy |= target_mask;
+            p->dtr_pending |= target_mask;
+            scb->flags |= SCB_MSGOUT_WDTR;
+          }
+          if ( p->transinfo[tindex].goal_offset )
+          {
+            p->needsdtr |= target_mask;
+            p->needsdtr_copy |= target_mask;
+            if( !(p->dtr_pending & target_mask) )
+            {
+              p->dtr_pending |= target_mask;
+              scb->flags |= SCB_MSGOUT_SDTR;
+            }
+          }
+          if ( p->dtr_pending & target_mask )
+          {
+            aic_outb(p, HOST_MSG, MSG_OUT);
+            aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
+          }
+        }
X         else if (scb->flags & SCB_MSGOUT_WDTR)
X         {
X           /*
@@ -4540,20 +4653,18 @@
X            */
X           p->needwdtr &= ~target_mask;
X           p->needwdtr_copy &= ~target_mask;
-          p->wdtr_pending &= ~target_mask;
+          p->dtr_pending &= ~target_mask;
X           scb->flags &= ~SCB_MSGOUT_BITS;
X           aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT,
X             (AHC_TRANS_ACTIVE|AHC_TRANS_GOAL|AHC_TRANS_CUR));
-          aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0,
+          aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
X                                AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
-          if ( (p->needsdtr_copy & target_mask) &&
-               !(p->sdtr_pending & target_mask) )
+          if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
X           {
-            p->sdtr_pending |= target_mask;
-            scb->flags |= SCB_MSGOUT_SDTR;
-            aic_outb(p, HOST_MSG, MSG_OUT);
-            aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+            printk(INFO_LEAD "Device is rejecting WDTR messages, using "
+              "narrow transfers.\n", p->host_no, channel, target, lun);
X           }
+          p->needsdtr |= (p->needsdtr_copy & target_mask);
X         }
X         else if (scb->flags & SCB_MSGOUT_SDTR)
X         {
@@ -4562,10 +4673,15 @@
X           */
X           p->needsdtr &= ~target_mask;
X           p->needsdtr_copy &= ~target_mask;
-          p->sdtr_pending &= ~target_mask;
+          p->dtr_pending &= ~target_mask;
X           scb->flags &= ~SCB_MSGOUT_SDTR;
-          aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0,
+          aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
X             (AHC_TRANS_CUR|AHC_TRANS_ACTIVE|AHC_TRANS_GOAL));
+          if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Device is rejecting SDTR messages, using "
+              "async transfers.\n", p->host_no, channel, target, lun);
+          }
X         }
X         else if (aic7xxx_verbose & VERBOSE_SEQINT)
X         {
@@ -4681,41 +4797,24 @@
X                  * However, if this SCB already was attempting to negotiate,
X                  * then we assume this isn't the problem and skip this part.
X                  */
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
X                 if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
X                      (p->dev_flags[tindex] & DEVICE_SCANNED) &&
-                     !(p->wdtr_pending & target_mask) && 
-                     !(p->sdtr_pending & target_mask) )
+                     !(p->dtr_pending & target_mask) ) 
X                 {
+                  p->needppr |= (p->needppr_copy & target_mask);
X                   p->needwdtr |= (p->needwdtr_copy & target_mask);
X                   p->needsdtr |= (p->needsdtr_copy & target_mask);
X                 }
-                else if ( (scb->cmd == p->dev_wdtr_cmnd[tindex]) ||
-                          (scb->cmd == p->dev_sdtr_cmnd[tindex]) )
+                else if ( scb->cmd == p->dev_dtr_cmnd[tindex] )
X                 {
X                   /*
X                    * This is already a negotiation command, so we must have
-                   * already done either WDTR or SDTR (or maybe both).  So
-                   * we simply check sdtr_pending and needsdtr to see if we
-                   * should throw out SDTR on this command.
-                   *
-                   * Note: Don't check the needsdtr_copy here, instead just
-                   * check to see if WDTR wiped out our SDTR and set needsdtr.
-                   * Even if WDTR did wipe out SDTR and set needsdtr, if
-                   * parse_msg() then turned around and started our SDTR
-                   * in back to back fasion, then conclusion of that should
-                   * have negated any needsdtr setting.  That's why we only
-                   * check needsdtr and sdtr_pending.
+                   * already done PPR, WDTR or SDTR.  Since our negotiation
+                   * could have gotten rejected, we don't really know the
+                   * full state of things.  Don't do anything here, and allow
+                   * the negotiation_complete() handler to do the right
+                   * thing.
X                    */
-                  scb->flags &= ~SCB_MSGOUT_BITS;
-                  if ( (scb->cmd == p->dev_wdtr_cmnd[tindex]) &&
-                       !(p->sdtr_pending & target_mask) &&
-                       (p->needsdtr & target_mask) )
-                  {
-                    p->sdtr_pending |= target_mask;
-                    hscb->control |= MK_MESSAGE;
-                    scb->flags |= SCB_MSGOUT_SDTR;
-                  }
X 
X                   /*
X                    * This is the important part though.  We are getting sense
@@ -4736,43 +4835,13 @@
X                     hscb->data_pointer = scb->sg_list[0].address;
X                   }
X                 }
-#else
-                if (  (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
-                     !(scb->flags & SCB_MSGOUT_BITS) && 
-                      (scb->cmd->lun == 0) &&
-                      (p->dev_flags[TARGET_INDEX(scb->cmd)] & DEVICE_SCANNED) )
-                {
-                  if ( (p->needwdtr_copy & target_mask) &&
-                      !(p->wdtr_pending & target_mask) &&
-                      !(p->sdtr_pending & target_mask) )
-                  {
-                    p->needwdtr |= target_mask;
-                    p->wdtr_pending |= target_mask;
-                    hscb->control |= MK_MESSAGE;
-                    scb->flags |= SCB_MSGOUT_WDTR;
-                  }
-                  if ( p->needsdtr_copy & target_mask )
-                  {
-                    p->needsdtr |= target_mask;
-                    if ( !(p->wdtr_pending & target_mask) &&
-                         !(p->sdtr_pending & target_mask) )
-                    {
-                      p->sdtr_pending |= target_mask;
-                      hscb->control |= MK_MESSAGE;
-                      scb->flags |= SCB_MSGOUT_SDTR;
-                    }
-                  }
-                }
-                else
-                  scb->flags &= ~SCB_MSGOUT_BITS;
-#endif /* AIC7XXX_FAKE_NEGOTIATION_CMDS */
X                 scb->flags |= SCB_SENSE;
X                 /*
X                  * Ensure the target is busy since this will be an
X                  * an untagged request.
X                  */
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
-                if (aic7xxx_verbose > 0xffff)
+                if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
X                 {
X                   if (scb->flags & SCB_MSGOUT_BITS)
X                     printk(INFO_LEAD "Requesting SENSE with %s\n", p->host_no,
@@ -4914,7 +4983,8 @@
X                 }
X               }
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
-              if (aic7xxx_verbose & VERBOSE_MINOR_ERROR)
+              if( (aic7xxx_verbose & VERBOSE_MINOR_ERROR) ||
+                  (aic7xxx_verbose > 0xffff) )
X               {
X                 if (queue_flag)
X                   printk(INFO_LEAD "Queue full received; queue depth %d, "
@@ -4928,8 +4998,6 @@
X #endif
X               if (queue_flag)
X               {
-                p->dev_temp_queue_depth[tindex] = 
-                  p->dev_active_cmds[tindex];
X                 if ( p->dev_last_queue_full[tindex] !=
X                      p->dev_active_cmds[tindex] )
X                 {
@@ -4951,10 +5019,28 @@
X                       p->dev_active_cmds[tindex];
X                   p->dev_last_queue_full[tindex] = 0;
X                   p->dev_last_queue_full_count[tindex] = 0;
+                  p->dev_temp_queue_depth[tindex] = 
+                    p->dev_active_cmds[tindex];
+                }
+                else if (p->dev_active_cmds[tindex] == 0)
+                {
+                  if (aic7xxx_verbose & VERBOSE_NEGOTIATION)
+                  {
+                    printk(INFO_LEAD "QUEUE_FULL status received with 0 "
+                           "commands active.\n", p->host_no, CTL_OF_SCB(scb));
+                    printk(INFO_LEAD "Tagged Command Queueing disabled\n",
+                           p->host_no, CTL_OF_SCB(scb));
+                  }
+                  p->dev_max_queue_depth[tindex] = 1;
+                  p->dev_temp_queue_depth[tindex] = 1;
+                  scb->tag_action = 0;
+                  scb->hscb->control &= ~(MSG_ORDERED_Q_TAG|MSG_SIMPLE_Q_TAG);
X                 }
X                 else
X                 {
X                   p->dev_flags[tindex] |= DEVICE_WAS_BUSY;
+                  p->dev_temp_queue_depth[tindex] = 
+                    p->dev_active_cmds[tindex];
X                 }
X               }
X               break;
@@ -4989,7 +5075,7 @@
X          */
X 
X         if ( !(scb->flags & SCB_DEVICE_RESET) &&
-              (aic_inb(p, MSG_OUT) == MSG_IDENTIFYFLAG) &&
+              (msg_out == MSG_IDENTIFYFLAG) &&
X               (scb->hscb->control & TAG_ENB) )
X         {
X           p->msg_buf[p->msg_index++] = scb->tag_action;
@@ -5020,34 +5106,68 @@
X             printk(INFO_LEAD "Abort message mailed.\n", p->host_no,
X               CTL_OF_SCB(scb));
X         }
-        else if (scb->flags & SCB_MSGOUT_WDTR)
+        else if (scb->flags & SCB_MSGOUT_PPR)
X         {
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-          if (aic7xxx_verbose > 0xffff)
+          unsigned int max_sync, period;
+          unsigned char options = p->transinfo[tindex].goal_options;
+
+          if (p->features & AHC_ULTRA2)
+          {
+            if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
+                !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
+            {
+              if( (p->features & AHC_ULTRA3) &&
+                  (p->dev_flags[tindex] & DEVICE_SCSI_3) &&
+                  (p->transinfo[tindex].goal_width ==
+                   MSG_EXT_WDTR_BUS_16_BIT) &&
+                  (options != 0) )
+              {
+                max_sync = AHC_SYNCRATE_ULTRA3;
+              }
+              else
+              {
+                max_sync = AHC_SYNCRATE_ULTRA2;
+              }
+            }
+            else
+            {
+              max_sync = AHC_SYNCRATE_ULTRA;
+            }
+          }
+          else if (p->features & AHC_ULTRA)
+          {
+            max_sync = AHC_SYNCRATE_ULTRA;
+          }
+          else
+          {
+            max_sync = AHC_SYNCRATE_FAST;
+          }
+          period = p->transinfo[tindex].goal_period;
+          aic7xxx_find_syncrate(p, &period, max_sync, &options);
+          p->transinfo[tindex].goal_period = period;
+          p->transinfo[tindex].goal_options = options;
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Sending PPR (%d/%d/%d/%d) message.\n",
+                   p->host_no, CTL_OF_SCB(scb), period,
+                   p->transinfo[tindex].goal_offset,
+                   p->transinfo[tindex].goal_width, options);
+          }
+          aic7xxx_construct_ppr(p, scb);
+        }
+        else if (scb->flags & SCB_MSGOUT_WDTR)
+        {
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
X             printk(INFO_LEAD "Sending WDTR message.\n", p->host_no,
X                    CTL_OF_SCB(scb));
-#endif
-          aic7xxx_construct_wdtr(p,
-            p->transinfo[TARGET_INDEX(scb->cmd)].goal_width);
+          }
+          aic7xxx_construct_wdtr(p, p->transinfo[tindex].goal_width);
X         }
X         else if (scb->flags & SCB_MSGOUT_SDTR)
X         {
X           unsigned int max_sync, period;
-          /*
-           * We need to set an accurate goal_offset instead of
-           * the ridiculously high one we default to.  We should
-           * now know if we are wide.  Plus, the WDTR code will 
-           * set our goal_offset for us as well.
-           */
-          if (p->transinfo[tindex].goal_offset)
-          {
-            if (p->features & AHC_ULTRA2)
-              p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
-            else if (p->transinfo[tindex].cur_width == MSG_EXT_WDTR_BUS_16_BIT)
-              p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
-            else
-              p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
-          }
+          unsigned char options = 0;
X           /*
X            * Now that the device is selected, use the bits in SBLKCTL and
X            * SSTAT2 to determine the max sync rate for this device.
@@ -5073,14 +5193,14 @@
X             max_sync = AHC_SYNCRATE_FAST;
X           }
X           period = p->transinfo[tindex].goal_period;
-          aic7xxx_find_syncrate(p, &period, max_sync);
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-          if (aic7xxx_verbose > 0xffff)
+          aic7xxx_find_syncrate(p, &period, max_sync, &options);
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
X             printk(INFO_LEAD "Sending SDTR %d/%d message.\n", p->host_no,
X                    CTL_OF_SCB(scb),
X                    p->transinfo[tindex].goal_period,
X                    p->transinfo[tindex].goal_offset);
-#endif
+          }
X           aic7xxx_construct_sdtr(p, period,
X             p->transinfo[tindex].goal_offset);
X         }
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 12'
echo 'File patch-2.2.10 is continued in part 13'
echo 13 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 14 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 14; 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
-  mask = (0x01 << TARGET_INDEX(cmd));
+  mask = (0x01 << tindex);
X   hscb = scb->hscb;
X 
X   /*
@@ -9757,11 +10437,12 @@
X   if (p->discenable & mask)
X   {
X     hscb->control |= DISCENB;
-    if (p->tagenable & mask)
+    if ( (p->tagenable & mask) &&
+         (cmd->cmnd[0] != TEST_UNIT_READY) )
X     {
X       cmd->tag = hscb->tag;
-      p->dev_commands_sent[TARGET_INDEX(cmd)]++;
-      if (p->dev_commands_sent[TARGET_INDEX(cmd)] < 200)
+      p->dev_commands_sent[tindex]++;
+      if (p->dev_commands_sent[tindex] < 200)
X       {
X         hscb->control |= MSG_SIMPLE_Q_TAG;
X         scb->tag_action = MSG_SIMPLE_Q_TAG;
@@ -9778,74 +10459,38 @@
X           hscb->control |= MSG_SIMPLE_Q_TAG;
X           scb->tag_action = MSG_SIMPLE_Q_TAG;
X         }
-        p->dev_commands_sent[TARGET_INDEX(cmd)] = 0;
+        p->dev_commands_sent[tindex] = 0;
X       }
X     }
X   }
-  if (p->dev_flags[TARGET_INDEX(cmd)] & DEVICE_SCANNED)
+  if ( cmd == p->dev_dtr_cmnd[tindex] )
X   {
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
-    if ( (p->needwdtr & mask) && !(p->wdtr_pending & mask) )
+    p->dtr_pending |= mask;
+    scb->tag_action = 0;
+    if (p->dev_flags[tindex] & DEVICE_SCANNED)
X     {
-      if (cmd == p->dev_wdtr_cmnd[TARGET_INDEX(cmd)])
+      hscb->control &= DISCENB;
+      hscb->control |= MK_MESSAGE;
+      if(p->needppr & mask)
X       {
-        p->wdtr_pending |= mask;
-        scb->flags |= SCB_MSGOUT_WDTR;
- hscb->control &= DISCENB;
-        hscb->control |= MK_MESSAGE;
-        scb->tag_action = 0;
+        scb->flags |= SCB_MSGOUT_PPR;
X       }
-      else
+      else if(p->needwdtr & mask)
X       {
-        aic7xxx_build_negotiation_cmnd(p, cmd, TARGET_INDEX(cmd));
+        scb->flags |= SCB_MSGOUT_WDTR;
X       }
-    }
-    else if ( (p->needsdtr & mask) && !(p->sdtr_pending & mask) &&
-              !(p->wdtr_pending & mask) )
-    {
-      if (cmd == p->dev_sdtr_cmnd[TARGET_INDEX(cmd)])
+      else if(p->needsdtr & mask)
X       {
-        p->sdtr_pending |= mask;
X         scb->flags |= SCB_MSGOUT_SDTR;
-        hscb->control &= DISCENB;
-        hscb->control |= MK_MESSAGE;
-        scb->tag_action = 0;
-      }
-      else if (cmd != p->dev_wdtr_cmnd[TARGET_INDEX(cmd)])
-      {
-        aic7xxx_build_negotiation_cmnd(p, cmd, TARGET_INDEX(cmd));
X       }
X     }
-#else
-    if ( (p->needwdtr & mask) && !(p->wdtr_pending & mask) &&
-         !(p->sdtr_pending & mask) && (cmd->lun == 0) )
-    {
-      p->wdtr_pending |= mask;
-      scb->flags |= SCB_MSGOUT_WDTR;
- hscb->control &= DISCENB;
-      hscb->control |= MK_MESSAGE;
- scb->tag_action = 0;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-      if (aic7xxx_verbose > 0xffff)
-        printk(INFO_LEAD "Building WDTR command.\n", p->host_no,
-               CTL_OF_CMD(cmd));
-#endif
-    }
-    else if ( (p->needsdtr & mask) && !(p->wdtr_pending & mask) &&
-              !(p->sdtr_pending & mask) && (cmd->lun == 0) )
-    {
-      p->sdtr_pending |= mask;
-      scb->flags |= SCB_MSGOUT_SDTR;
- hscb->control &= DISCENB;
-      hscb->control |= MK_MESSAGE;
- scb->tag_action = 0;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-      if (aic7xxx_verbose > 0xffff)
-        printk(INFO_LEAD "Building SDTR command.\n", p->host_no,
-               CTL_OF_CMD(cmd));
-#endif
-    }
-#endif
+  }
+  if ( !(p->dtr_pending & mask) &&
+        ( (p->needppr & mask) ||
+          (p->needwdtr & mask) ||
+          (p->needsdtr & mask) ) )
+  {
+    aic7xxx_build_negotiation_cmnd(p, cmd, tindex);
X   }
X   hscb->target_channel_lun = ((cmd->target << 4) & 0xF0) |
X         ((cmd->channel & 0x01) << 3) | (cmd->lun & 0x07);
@@ -9897,7 +10542,6 @@
X     scb->sg_count = cmd->use_sg;
X     hscb->SG_segment_count = cmd->use_sg;
X     hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(&scb->sg_list[1]));
-
X   }
X   else
X   {
@@ -9922,12 +10566,6 @@
X       hscb->data_pointer = 0;
X     }
X   }
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-  if((cmd->cmnd[0] == TEST_UNIT_READY) && (aic7xxx_verbose & VERBOSE_PROBE2))
-  {
-    aic7xxx_print_scb(p, scb);
-  }
-#endif
X }
X 
X /*+F*************************************************************************
@@ -10262,13 +10900,14 @@
X     if(p->dev_flags[i] & DEVICE_PRESENT)
X     {
X       mask = (0x01 << i);
-      printk(INFO_LEAD "dev_flags=0x%x, WDTR:%c/%c/%c, SDTR:%c/%c/%c,"
-             " q_depth=%d:%d\n",
+      printk(INFO_LEAD "dev_flags=0x%x, Pending:%c, PPR:%c/%c, WDTR:%c/%c, "
+             "SDTR:%c/%c, q_depth=%d:%d\n",
X         p->host_no, 0, i, 0, p->dev_flags[i],
-        (p->wdtr_pending & mask) ? 'Y' : 'N',
+        (p->dtr_pending & mask) ? 'Y' : 'N',
+        (p->needppr & mask) ? 'Y' : 'N',
+        (p->needppr_copy & mask) ? 'Y' : 'N',
X         (p->needwdtr & mask) ? 'Y' : 'N',
X         (p->needwdtr_copy & mask) ? 'Y' : 'N',
-        (p->sdtr_pending & mask) ? 'Y' : 'N',
X         (p->needsdtr & mask) ? 'Y' : 'N',
X         (p->needsdtr_copy & mask) ? 'Y' : 'N',
X         p->dev_active_cmds[i],
@@ -10347,13 +10986,13 @@
X      * We haven't found the offending SCB yet, and it should be around
X      * somewhere, so go look for it in the cards SCBs.
X      */
-    printk("SCBPTR CONTROL TAG PREV NEXT\n");
+    printk("SCBPTR CONTROL TAG NEXT\n");
X     for(i=0; i<p->scb_data->maxhscbs; i++)
X     {
X       aic_outb(p, i, SCBPTR);
-      printk("   %3d      %02x  %02x   %02x   %02x\n", i,
+      printk("   %3d      %02x  %02x   %02x\n", i,
X              aic_inb(p, SCB_CONTROL), aic_inb(p, SCB_TAG),
-             aic_inb(p, SCB_PREV), aic_inb(p, SCB_NEXT));
+             aic_inb(p, SCB_NEXT));
X     }
X   }
X   
@@ -10569,21 +11208,13 @@
X   if ((found == 0) && (scb->flags & SCB_WAITINGQ))
X   {
X     int tindex = TARGET_INDEX(cmd);
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
X     unsigned short mask;
X 
X     mask = (1 << tindex);
X 
-    if (p->wdtr_pending & mask)
-    {
-      if (p->dev_wdtr_cmnd[tindex]->next != cmd)
-        found = 1;
-      else
-        found = 0;
-    }
-    else if (p->sdtr_pending & mask)
+    if (p->dtr_pending & mask)
X     {
-      if (p->dev_sdtr_cmnd[tindex]->next != cmd)
+      if (p->dev_dtr_cmnd[tindex]->next != cmd)
X         found = 1;
X       else
X         found = 0;
@@ -10606,7 +11237,6 @@
X       DRIVER_UNLOCK
X       return(SCSI_ABORT_PENDING);
X     }
-#endif
X     if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS) 
X       printk(INFO_LEAD "SCB found on waiting list and "
X           "aborted.\n", p->host_no, CTL_OF_SCB(scb));
@@ -10864,6 +11494,8 @@
X       if(aic7xxx_verbose & VERBOSE_RESET_RETURN)
X         printk(INFO_LEAD "SCB on qoutfifo, returning.\n", p->host_no,
X           CTL_OF_SCB(scb));
+      aic7xxx_run_done_queue(p, TRUE);
+      aic7xxx_run_waiting_queues(p);
X       unpause_sequencer(p, FALSE);
X       DRIVER_UNLOCK
X       return(SCSI_RESET_NOT_RUNNING);
@@ -11034,16 +11666,21 @@
X int
X aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[])
X {
-  int heads, sectors, cylinders;
+  int heads, sectors, cylinders, ret;
X   struct aic7xxx_host *p;
+  struct buffer_head *bh;
X 
X   p = (struct aic7xxx_host *) disk->device->host->hostdata;
+  bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024);
X 
-  /*
-   * XXX - if I could portably find the card's configuration
-   *       information, then this could be autodetected instead
-   *       of left to a boot-time switch.
-   */
+  if ( bh )
+  {
+    ret = scsi_partsize(bh, disk->capacity, &geom[2], &geom[0], &geom[1]);
+    brelse(bh);
+    if ( ret != -1 )
+      return(ret);
+  }
+  
X   heads = 64;
X   sectors = 32;
X   cylinders = disk->capacity / (heads * sectors);
@@ -11150,6 +11787,12 @@
X           0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9f, 0x9f,
X           0xe0, 0xf1, 0xf4, 0xf4, 0xf6, 0xf6, 0xf8, 0xf8, 0xfa, 0xfc,
X           0xfe, 0xff} },
+    {12, {0x00, 0x05, 0x08, 0x11, 0x18, 0x1f, 0x60, 0x60, 0x62, 0x66, /*7892*/
+          0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
+          0xe0, 0xf1, 0xf4, 0xfc} },
+    {12, {0x00, 0x05, 0x08, 0x11, 0x18, 0x1f, 0x60, 0x60, 0x62, 0x66, /*7899*/
+          0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
+          0xe0, 0xf1, 0xf4, 0xfc} },
X   };
X #ifdef CONFIG_PCI
X   static struct register_ranges cards_ns[] = {
@@ -11164,6 +11807,10 @@
X     { 5, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3} },
X     { 6, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x30, 0x34, 0x3c, 0x47,
X           0xdc, 0xe3} },
+    { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
+          0xff, 0xff} },
+    { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
+          0xff, 0xff} },
X     { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
X           0xff, 0xff} }
X   };
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- v2.2.9/linux/drivers/scsi/aic7xxx_proc.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/scsi/aic7xxx_proc.c	Wed Jun  9 16:59:34 1999
@@ -160,21 +160,17 @@
X   size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
X   size += sprintf(BLS, "\n");
X   size += sprintf(BLS, "Compile Options:\n");
-#ifdef AIC7XXX_RESET_DELAY
-  size += sprintf(BLS, "  AIC7XXX_RESET_DELAY    : %d\n", AIC7XXX_RESET_DELAY);
+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+  size += sprintf(BLS, "  TCQ Enabled By Default : Enabled\n");
+#else
+  size += sprintf(BLS, "  TCQ Enabled By Default : Disabled\n");
X #endif
-  size += sprintf(BLS, "  AIC7XXX_TAGGED_QUEUEING: Adapter Support Enabled\n");
-  size += sprintf(BLS, "                             Check below to see "
-                       "which\n"
-                       "                             devices use tagged "
-                       "queueing\n");
-  size += sprintf(BLS, "  AIC7XXX_PAGE_ENABLE    : Enabled (This is no longer "
-                       "an option)\n");
X #ifdef AIC7XXX_PROC_STATS
X   size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Enabled\n");
X #else
X   size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Disabled\n");
X #endif
+  size += sprintf(BLS, "  AIC7XXX_RESET_DELAY    : %d\n", AIC7XXX_RESET_DELAY);
X   size += sprintf(BLS, "\n");
X   size += sprintf(BLS, "Adapter Configuration:\n");
X   size += sprintf(BLS, "           SCSI Adapter: %s\n",
@@ -194,8 +190,21 @@
X     }
X     if (p->features & AHC_WIDE)
X       wide = "Wide ";
-    if (p->features & AHC_ULTRA2)
-      ultra = "Ultra2-LVD/SE ";
+    if (p->features & AHC_ULTRA3)
+    {
+      switch(p->chip & AHC_CHIPID_MASK)
+      {
+        case AHC_AIC7892:
+        case AHC_AIC7899:
+          ultra = "Ultra-160/m LVD/SE ";
+          break;
+        default:
+          ultra = "Ultra-3 LVD/SE ";
+          break;
+      }
+    }
+    else if (p->features & AHC_ULTRA2)
+      ultra = "Ultra-2 LVD/SE ";
X     else if (p->features & AHC_ULTRA)
X       ultra = "Ultra ";
X     size += sprintf(BLS, "                           %s%sController%s\n",
@@ -250,11 +259,7 @@
X   }
X   size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable);
X   size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag);
-#ifdef AIC7XXX_CMDS_PER_LUN
-  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_LUN);
-#else
-  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", 8);
-#endif
+  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE);
X   size += sprintf(BLS, "    Tagged Queue By Device array for aic7xxx host "
X                        "instance %d:\n", p->instance);
X   size += sprintf(BLS, "      {");
@@ -295,11 +300,12 @@
X     if (p->transinfo[target].cur_offset != 0)
X     {
X       struct aic7xxx_syncrate *sync_rate;
+      unsigned char options = p->transinfo[target].cur_options;
X       int period = p->transinfo[target].cur_period;
X       int rate = (p->transinfo[target].cur_width ==
X                   MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
X 
-      sync_rate = aic7xxx_find_syncrate(p, &period, AHC_SYNCRATE_ULTRA2);
+      sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
X       if (sync_rate != NULL)
X       {
X         size += sprintf(BLS, "%s MByte/sec, offset %d\n",
@@ -313,18 +319,21 @@
X       }
X     }
X     size += sprintf(BLS, "  Transinfo settings: ");
-    size += sprintf(BLS, "current(%d/%d/%d), ",
+    size += sprintf(BLS, "current(%d/%d/%d/%d), ",
X                     p->transinfo[target].cur_period,
X                     p->transinfo[target].cur_offset,
-                    p->transinfo[target].cur_width);
-    size += sprintf(BLS, "goal(%d/%d/%d), ",
+                    p->transinfo[target].cur_width,
+                    p->transinfo[target].cur_options);
+    size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
X                     p->transinfo[target].goal_period,
X                     p->transinfo[target].goal_offset,
-                    p->transinfo[target].goal_width);
-    size += sprintf(BLS, "user(%d/%d/%d)\n",
+                    p->transinfo[target].goal_width,
+                    p->transinfo[target].goal_options);
+    size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
X                     p->transinfo[target].user_period,
X                     p->transinfo[target].user_offset,
-                    p->transinfo[target].user_width);
+                    p->transinfo[target].user_width,
+                    p->transinfo[target].user_options);
X #ifdef AIC7XXX_PROC_STATS
X     size += sprintf(BLS, "  Total transfers %ld (%ld reads and %ld writes)\n",
X         sp->r_total + sp->w_total, sp->r_total, sp->w_total);
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h
--- v2.2.9/linux/drivers/scsi/aic7xxx_reg.h	Fri Oct  9 13:27:11 1998
+++ linux/drivers/scsi/aic7xxx_reg.h	Wed Jun  9 16:59:34 1999
@@ -63,6 +63,16 @@
X 
X #define	STCNT           		0x08
X 
+#define	OPTIONMODE      		0x08
+#define		AUTORATEEN      	0x80
+#define		AUTOACKEN       	0x40
+#define		ATNMGMNTEN      	0x20
+#define		BUSFREEREV      	0x10
+#define		EXPPHASEDIS     	0x08
+#define		SCSIDATL_IMGEN  	0x04
+#define		AUTO_MSGOUT_DE  	0x02
+#define		DIS_MSGIN_DUALEDGE	0x01
+
X #define	CLRSINT0        		0x0b
X #define		CLRSELDO        	0x40
X #define		CLRSELDI        	0x20
@@ -102,8 +112,14 @@
X 
X #define	SSTAT2          		0x0d
X #define		OVERRUN         	0x80
+#define		SHVALID         	0x40
+#define		WIDE_RES        	0x20
X #define		SFCNT           	0x1f
X #define		EXP_ACTIVE      	0x10
+#define		CRCVALERR       	0x08
+#define		CRCENDERR       	0x04
+#define		CRCREQERR       	0x02
+#define		DUAL_EDGE_ERROR 	0x01
X 
X #define	SSTAT3          		0x0e
X #define		SCSICNT         	0xf0
@@ -412,6 +428,7 @@
X #define		DPARERR         	0x10
X #define		SQPARERR        	0x08
X #define		ILLOPCODE       	0x04
+#define		DSCTMOUT        	0x02
X #define		ILLSADDR        	0x02
X #define		ILLHADDR        	0x01
X 
@@ -436,11 +453,30 @@
X 
X #define	QINCNT          		0x9c
X 
+#define	SCSIDATL_IMG    		0x9c
+
X #define	QOUTFIFO        		0x9d
X 
+#define	CRCCONTROL1     		0x9d
+#define		CRCONSEEN       	0x80
+#define		TARGCRCCNTEN    	0x40
+#define		CRCVALCHKEN     	0x40
+#define		CRCENDCHKEN     	0x20
+#define		CRCREQCHKEN     	0x10
+#define		TARGCRCENDEN    	0x08
+
+#define	SCSIPHASE       		0x9e
+#define		SP_STATUS       	0x20
+#define		SP_COMMAND      	0x10
+#define		SP_MSG_IN       	0x08
+#define		SP_MSG_OUT      	0x04
+#define		SP_DATA_IN      	0x02
+#define		SP_DATA_OUT     	0x01
+
X #define	QOUTCNT         		0x9e
X 
X #define	SFUNCT          		0x9f
+#define		ALT_MODE        	0x80
X 
X #define	SCB_CONTROL     		0xa0
X #define		MK_MESSAGE      	0x80
@@ -525,14 +561,20 @@
X 
X #define	HNSCB_QOFF      		0xf4
X 
+#define	HESCB_QOFF      		0xf5
+
X #define	SNSCB_QOFF      		0xf6
X 
+#define	SESCB_QOFF      		0xf7
+
X #define	SDSCB_QOFF      		0xf8
X 
X #define	QOFF_CTLSTA     		0xfa
+#define		ESTABLISH_SCB_AVAIL	0x80
X #define		SCB_AVAIL       	0x40
X #define		SNSCB_ROLLOVER  	0x20
X #define		SDSCB_ROLLOVER  	0x10
+#define		SESCB_ROLLOVER  	0x08
X #define		SCB_QSIZE       	0x07
X #define		SCB_QSIZE_256   	0x06
X 
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/aic7xxx_seq.c linux/drivers/scsi/aic7xxx_seq.c
--- v2.2.9/linux/drivers/scsi/aic7xxx_seq.c	Fri Oct  9 13:27:11 1998
+++ linux/drivers/scsi/aic7xxx_seq.c	Wed Jun  9 16:59:34 1999
@@ -3,38 +3,44 @@
X   */
X static unsigned char seqprog[] = {
X 	0xff, 0x6a, 0x06, 0x08,
+	0x7f, 0x02, 0x04, 0x08,
X 	0x32, 0x6a, 0x00, 0x00,
X 	0x12, 0x6a, 0x00, 0x00,
X 	0xff, 0x6a, 0xd6, 0x09,
X 	0xff, 0x6a, 0xdc, 0x09,
-	0x00, 0x65, 0x38, 0x59,
+	0x00, 0x65, 0x42, 0x59,
X 	0xf7, 0x01, 0x02, 0x08,
X 	0xff, 0x4e, 0xc8, 0x08,
X 	0xbf, 0x60, 0xc0, 0x08,
-	0x60, 0x0b, 0x7c, 0x68,
+	0x60, 0x0b, 0x86, 0x68,
X 	0x40, 0x00, 0x0e, 0x68,
X 	0x08, 0x1f, 0x3e, 0x10,
-	0x60, 0x0b, 0x7c, 0x68,
+	0x60, 0x0b, 0x86, 0x68,
X 	0x40, 0x00, 0x0e, 0x68,
X 	0x08, 0x1f, 0x3e, 0x10,
-	0xff, 0x3e, 0x3e, 0x60,
-	0x40, 0xfa, 0x10, 0x78,
+	0xff, 0x3e, 0x4a, 0x60,
+	0x40, 0xfa, 0x12, 0x78,
X 	0xff, 0xf6, 0xd4, 0x08,
X 	0x01, 0x4e, 0x9c, 0x18,
X 	0x40, 0x60, 0xc0, 0x00,
-	0x00, 0x4d, 0x10, 0x70,
+	0x00, 0x4d, 0x12, 0x70,
X 	0x01, 0x4e, 0x9c, 0x18,
X 	0xbf, 0x60, 0xc0, 0x08,
-	0x00, 0x6a, 0x72, 0x5c,
+	0x00, 0x6a, 0x92, 0x5c,
X 	0xff, 0x4e, 0xc8, 0x18,
-	0x02, 0x6a, 0x88, 0x5b,
+	0x02, 0x6a, 0xa8, 0x5b,
X 	0xff, 0x52, 0x20, 0x09,
X 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x52, 0xfe, 0x5b,
+	0x00, 0x52, 0x1e, 0x5c,
+	0x03, 0xb0, 0x52, 0x31,
+	0xff, 0xb0, 0x52, 0x09,
+	0xff, 0xb1, 0x54, 0x09,
+	0xff, 0xb2, 0x56, 0x09,
+	0xff, 0xa3, 0x50, 0x09,
X 	0xff, 0x3e, 0x74, 0x09,
X 	0xff, 0x90, 0x7c, 0x08,
X 	0xff, 0x3e, 0x20, 0x09,
-	0x00, 0x65, 0x44, 0x58,
+	0x00, 0x65, 0x50, 0x58,
X 	0x00, 0x65, 0x0e, 0x40,
X 	0xf7, 0x1f, 0xca, 0x08,
X 	0x08, 0xa1, 0xc8, 0x08,
@@ -47,51 +53,50 @@
X 	0x0f, 0x05, 0x0a, 0x08,
X 	0x00, 0x05, 0x0a, 0x00,
X 	0x5a, 0x6a, 0x00, 0x04,
-	0x12, 0x65, 0xc8, 0x00,
-	0x00, 0x01, 0x02, 0x00,
+	0x12, 0x65, 0x02, 0x00,
X 	0x31, 0x6a, 0xca, 0x00,
-	0x80, 0x37, 0x64, 0x68,
+	0x80, 0x37, 0x6e, 0x68,
X 	0xff, 0x65, 0xca, 0x18,
X 	0xff, 0x37, 0xdc, 0x08,
X 	0xff, 0x6e, 0xc8, 0x08,
-	0x00, 0x6c, 0x6c, 0x78,
+	0x00, 0x6c, 0x76, 0x78,
X 	0x20, 0x01, 0x02, 0x00,
X 	0x4c, 0x37, 0xc8, 0x28,
-	0x08, 0x1f, 0x74, 0x78,
+	0x08, 0x1f, 0x7e, 0x78,
X 	0x08, 0x37, 0x6e, 0x00,
X 	0x08, 0x64, 0xc8, 0x00,
X 	0x70, 0x64, 0xca, 0x18,
X 	0xff, 0x6c, 0x0a, 0x08,
X 	0x20, 0x64, 0xca, 0x18,
X 	0xff, 0x6c, 0x08, 0x0c,
-	0x40, 0x0b, 0x04, 0x69,
-	0x80, 0x0b, 0xf6, 0x78,
+	0x40, 0x0b, 0x0e, 0x69,
+	0x80, 0x0b, 0x00, 0x79,
X 	0xa4, 0x6a, 0x06, 0x00,
X 	0x40, 0x6a, 0x16, 0x00,
-	0x10, 0x03, 0xf2, 0x78,
+	0x10, 0x03, 0xfc, 0x78,
X 	0xff, 0x50, 0xc8, 0x08,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0x49, 0x6a, 0xee, 0x5b,
+	0x49, 0x6a, 0x0e, 0x5c,
X 	0x01, 0x6a, 0x26, 0x01,
X 	0xff, 0x6a, 0xca, 0x08,
X 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x92, 0x78,
+	0x02, 0x0b, 0x9c, 0x78,
X 	0xf7, 0x01, 0x02, 0x08,
X 	0xff, 0x06, 0xcc, 0x08,
X 	0xff, 0x66, 0x32, 0x09,
X 	0x01, 0x65, 0xca, 0x18,
-	0x80, 0x66, 0xa0, 0x78,
+	0x80, 0x66, 0xaa, 0x78,
X 	0xff, 0x66, 0xa2, 0x08,
-	0x10, 0x03, 0x90, 0x68,
+	0x10, 0x03, 0x9a, 0x68,
X 	0xfc, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0xa8, 0x48,
+	0x00, 0x65, 0xb2, 0x48,
X 	0xff, 0x6a, 0x32, 0x01,
X 	0x01, 0x64, 0x18, 0x19,
X 	0xff, 0x6a, 0x1a, 0x09,
X 	0xff, 0x6a, 0x1c, 0x09,
X 	0x84, 0x6a, 0x06, 0x00,
X 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0xb2, 0x78,
+	0x02, 0x0b, 0xbc, 0x78,
X 	0xff, 0x06, 0xc8, 0x08,
X 	0xff, 0x64, 0x32, 0x09,
X 	0xff, 0x6a, 0xca, 0x08,
@@ -105,33 +110,33 @@
X 	0x0b, 0x65, 0xca, 0x18,
X 	0xff, 0x65, 0xc8, 0x08,
X 	0x00, 0x8c, 0x18, 0x19,
-	0x02, 0x0b, 0xce, 0x78,
-	0x01, 0x65, 0xd4, 0x60,
+	0x02, 0x0b, 0xd8, 0x78,
+	0x01, 0x65, 0xde, 0x60,
X 	0xf7, 0x01, 0x02, 0x08,
X 	0xff, 0x06, 0x32, 0x09,
X 	0xff, 0x65, 0xca, 0x18,
-	0xff, 0x65, 0xce, 0x68,
+	0xff, 0x65, 0xd8, 0x68,
X 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x64, 0x5c,
-	0x40, 0x51, 0xe6, 0x78,
+	0x00, 0x65, 0x84, 0x5c,
+	0x40, 0x51, 0xf0, 0x78,
X 	0xe4, 0x6a, 0x06, 0x00,
X 	0x08, 0x01, 0x02, 0x00,
-	0x04, 0x6a, 0x18, 0x5b,
+	0x04, 0x6a, 0x40, 0x5b,
X 	0x01, 0x50, 0xa0, 0x18,
-	0x00, 0x50, 0xec, 0xe0,
+	0x00, 0x50, 0xf6, 0xe0,
X 	0xff, 0x6a, 0xa0, 0x08,
X 	0xff, 0x6a, 0x3a, 0x01,
X 	0x02, 0x6a, 0x22, 0x01,
-	0x40, 0x51, 0xf2, 0x68,
+	0x40, 0x51, 0xfc, 0x68,
X 	0xff, 0x6a, 0x06, 0x08,
X 	0x00, 0x65, 0x0e, 0x40,
X 	0x20, 0x6a, 0x16, 0x00,
X 	0xf0, 0x19, 0x6e, 0x08,
X 	0x08, 0x6a, 0x18, 0x00,
X 	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x5a, 0x58,
+	0x08, 0x6a, 0x66, 0x58,
X 	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0x18, 0x41,
+	0x00, 0x65, 0x22, 0x41,
X 	0x12, 0x6a, 0x00, 0x00,
X 	0x40, 0x6a, 0x16, 0x00,
X 	0xff, 0x3e, 0x20, 0x09,
@@ -139,362 +144,373 @@
X 	0xff, 0xa1, 0x6e, 0x08,
X 	0x08, 0x6a, 0x18, 0x00,
X 	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x5a, 0x58,
+	0x08, 0x6a, 0x66, 0x58,
X 	0x80, 0x6a, 0x68, 0x00,
X 	0x80, 0x36, 0x6c, 0x00,
-	0x00, 0x65, 0xd2, 0x5b,
+	0x00, 0x65, 0xf2, 0x5b,
X 	0xff, 0x3d, 0xc8, 0x08,
-	0xbf, 0x64, 0x48, 0x79,
-	0x80, 0x64, 0xf0, 0x71,
-	0xa0, 0x64, 0x0e, 0x72,
-	0xc0, 0x64, 0x08, 0x72,
-	0xe0, 0x64, 0x52, 0x72,
+	0xbf, 0x64, 0x58, 0x79,
+	0x80, 0x64, 0x0e, 0x72,
+	0xa0, 0x64, 0x3a, 0x72,
+	0xc0, 0x64, 0x32, 0x72,
+	0xe0, 0x64, 0x7a, 0x72,
X 	0x01, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x18, 0x41,
+	0x00, 0x65, 0x22, 0x41,
X 	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0x38, 0x59,
+	0x00, 0x65, 0x42, 0x59,
X 	0xff, 0x06, 0xd4, 0x08,
X 	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0x32, 0x79,
+	0x09, 0x0c, 0x3c, 0x79,
X 	0x08, 0x0c, 0x0e, 0x68,
X 	0x01, 0x6a, 0x22, 0x01,
X 	0xff, 0x6a, 0x26, 0x09,
+	0x02, 0x6a, 0x08, 0x30,
X 	0xff, 0x6a, 0x08, 0x08,
X 	0xdf, 0x01, 0x02, 0x08,
X 	0x01, 0x6a, 0x7a, 0x00,
-	0x03, 0x36, 0x6c, 0x0c,
+	0xff, 0x6a, 0x6c, 0x0c,
+	0x03, 0xa9, 0x18, 0x31,
+	0x03, 0xa9, 0x10, 0x30,
X 	0x08, 0x6a, 0xcc, 0x00,
-	0xa9, 0x6a, 0xe8, 0x5b,
-	0x00, 0x65, 0x66, 0x41,
+	0xa9, 0x6a, 0x08, 0x5c,
+	0x00, 0x65, 0x78, 0x41,
X 	0xa8, 0x6a, 0x6a, 0x00,
X 	0x79, 0x6a, 0x6a, 0x00,
-	0x40, 0x3d, 0x50, 0x69,
+	0x40, 0x3d, 0x60, 0x69,
X 	0x04, 0x35, 0x6a, 0x00,
-	0x00, 0x65, 0x3a, 0x5b,
+	0x00, 0x65, 0x62, 0x5b,
X 	0x80, 0x6a, 0xd4, 0x01,
-	0x10, 0x36, 0x42, 0x69,
+	0x10, 0x36, 0x4e, 0x69,
X 	0x10, 0x36, 0x6c, 0x00,
X 	0x07, 0xac, 0x10, 0x31,
+	0x03, 0x8c, 0x10, 0x30,
+	0x05, 0xa3, 0x70, 0x30,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0xe0, 0x5b,
-	0x00, 0x65, 0xda, 0x5b,
-	0xff, 0xa3, 0x70, 0x08,
-	0x39, 0x6a, 0xcc, 0x00,
-	0xa4, 0x6a, 0xe6, 0x5b,
-	0xff, 0x38, 0x74, 0x69,
+	0xac, 0x6a, 0x00, 0x5c,
+	0x00, 0x65, 0xfa, 0x5b,
+	0x38, 0x6a, 0xcc, 0x00,
+	0xa3, 0x6a, 0x04, 0x5c,
+	0xff, 0x38, 0x88, 0x69,
X 	0x80, 0x02, 0x04, 0x00,
X 	0xe7, 0x35, 0x6a, 0x08,
X 	0x03, 0x69, 0x18, 0x31,
+	0x03, 0x69, 0x10, 0x30,
X 	0xff, 0x6a, 0x10, 0x00,
X 	0xff, 0x6a, 0x12, 0x00,
X 	0xff, 0x6a, 0x14, 0x00,
-	0x01, 0x38, 0x7a, 0x61,
-	0x02, 0xfc, 0xf8, 0x01,
+	0x01, 0x38, 0x8c, 0x61,
X 	0xbf, 0x35, 0x6a, 0x08,
X 	0xff, 0x69, 0xca, 0x08,
X 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0x7e, 0x69,
-	0x04, 0x0b, 0x8a, 0x69,
-	0x10, 0x0c, 0x80, 0x79,
-	0x04, 0x0b, 0x88, 0x69,
+	0x04, 0x0b, 0x90, 0x69,
+	0x04, 0x0b, 0x9c, 0x69,
+	0x10, 0x0c, 0x92, 0x79,
+	0x04, 0x0b, 0x9a, 0x69,
X 	0xff, 0x6a, 0xca, 0x08,
-	0x00, 0x35, 0x22, 0x5b,
-	0x80, 0x02, 0xd6, 0x69,
-	0xff, 0x65, 0xc8, 0x79,
+	0x00, 0x35, 0x4a, 0x5b,
+	0x80, 0x02, 0xf0, 0x69,
+	0xff, 0x65, 0xe0, 0x79,
X 	0xff, 0x38, 0x70, 0x18,
-	0xff, 0x38, 0xc8, 0x79,
-	0x80, 0xea, 0xaa, 0x61,
+	0xff, 0x38, 0xe0, 0x79,
+	0x80, 0xea, 0xbc, 0x61,
X 	0xef, 0x38, 0xc8, 0x18,
X 	0x80, 0x6a, 0xc8, 0x00,
-	0x00, 0x65, 0x9c, 0x49,
+	0x00, 0x65, 0xae, 0x49,
X 	0x33, 0x38, 0xc8, 0x28,
X 	0xff, 0x64, 0xd0, 0x09,
X 	0x04, 0x39, 0xc0, 0x31,
X 	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0xa2, 0x79,
+	0x80, 0xeb, 0xb4, 0x79,
X 	0xf7, 0xeb, 0xd6, 0x09,
-	0x08, 0xeb, 0xa6, 0x69,
+	0x08, 0xeb, 0xb8, 0x69,
X 	0x01, 0x6a, 0xd6, 0x01,
X 	0x08, 0xe9, 0x10, 0x31,
+	0x03, 0x8c, 0x10, 0x30,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0x39, 0x6a, 0xe6, 0x5b,
+	0x39, 0x6a, 0x06, 0x5c,
X 	0x08, 0x6a, 0x18, 0x01,
X 	0xff, 0x6a, 0x1a, 0x09,
X 	0xff, 0x6a, 0x1c, 0x09,
X 	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x64, 0x5c,
-	0x88, 0x6a, 0x54, 0x5c,
-	0x00, 0x65, 0xda, 0x5b,
+	0x00, 0x65, 0x84, 0x5c,
+	0x88, 0x6a, 0x74, 0x5c,
+	0x00, 0x65, 0xfa, 0x5b,
X 	0xff, 0x6a, 0xc8, 0x08,
X 	0x08, 0x39, 0x72, 0x18,
X 	0x00, 0x3a, 0x74, 0x20,
-	0x10, 0x0c, 0x66, 0x79,
-	0x80, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xe0, 0x59,
+	0x01, 0x0c, 0xd8, 0x79,
+	0x10, 0x0c, 0x78, 0x79,
+	0xff, 0x35, 0x26, 0x09,
+	0x04, 0x0b, 0xde, 0x69,
+	0x00, 0x65, 0xf8, 0x59,
+	0x03, 0x08, 0x52, 0x31,
+	0xff, 0x38, 0x50, 0x09,
X 	0xff, 0x08, 0x52, 0x09,
X 	0xff, 0x09, 0x54, 0x09,
X 	0xff, 0x0a, 0x56, 0x09,
X 	0xff, 0x38, 0x50, 0x09,
-	0x12, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0x18, 0x41,
-	0x00, 0x65, 0xe0, 0x59,
-	0x12, 0x01, 0x02, 0x00,
+	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0xf8, 0x59,
X 	0x7f, 0x02, 0x04, 0x08,
X 	0xe1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x18, 0x41,
-	0x04, 0x93, 0xea, 0x69,
+	0x00, 0x65, 0x22, 0x41,
+	0x04, 0x93, 0x02, 0x6a,
X 	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0xe4, 0x69,
+	0x20, 0x93, 0xfc, 0x69,
X 	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0xe6, 0x79,
+	0x01, 0x94, 0xfe, 0x79,
X 	0xd7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0xec, 0x69,
+	0x08, 0x93, 0x04, 0x6a,
+	0x03, 0x08, 0x52, 0x31,
+	0xff, 0x38, 0x50, 0x09,
+	0x12, 0x01, 0x02, 0x00,
X 	0xff, 0x6a, 0xd4, 0x0c,
-	0x00, 0x65, 0x3a, 0x5b,
-	0x02, 0xfc, 0xf8, 0x01,
+	0x00, 0x65, 0x62, 0x5b,
X 	0x05, 0xb4, 0x10, 0x31,
X 	0x02, 0x6a, 0x1a, 0x31,
+	0x03, 0x8c, 0x10, 0x30,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0xb4, 0x6a, 0xe4, 0x5b,
+	0xb4, 0x6a, 0x04, 0x5c,
X 	0xff, 0x6a, 0x1a, 0x09,
X 	0xff, 0x6a, 0x1c, 0x09,
-	0x00, 0x65, 0xda, 0x5b,
-	0x3d, 0x6a, 0x22, 0x5b,
-	0xac, 0x6a, 0x22, 0x5b,
-	0x00, 0x65, 0x18, 0x41,
-	0x00, 0x65, 0x3a, 0x5b,
+	0x00, 0x65, 0xfa, 0x5b,
+	0x3d, 0x6a, 0x4a, 0x5b,
+	0xac, 0x6a, 0x26, 0x01,
+	0x04, 0x0b, 0x24, 0x6a,
+	0x01, 0x0b, 0x2a, 0x6a,
+	0x10, 0x0c, 0x26, 0x7a,
+	0xd7, 0x93, 0x26, 0x09,
+	0x08, 0x93, 0x2c, 0x6a,
+	0x12, 0x01, 0x02, 0x00,
+	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0x62, 0x5b,
X 	0xff, 0x06, 0x44, 0x09,
-	0x00, 0x65, 0x18, 0x41,
+	0x00, 0x65, 0x22, 0x41,
+	0x10, 0x3d, 0x06, 0x00,
X 	0xff, 0x34, 0xca, 0x08,
-	0x80, 0x65, 0x32, 0x62,
+	0x80, 0x65, 0x5e, 0x62,
X 	0x0f, 0xa1, 0xca, 0x08,
X 	0x07, 0xa1, 0xca, 0x08,
X 	0x40, 0xa0, 0xc8, 0x08,
X 	0x00, 0x65, 0xca, 0x00,
X 	0x80, 0x65, 0xca, 0x00,
-	0x80, 0xa0, 0x22, 0x7a,
+	0x80, 0xa0, 0x4e, 0x7a,
X 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x34, 0x42,
-	0x20, 0xa0, 0x3a, 0x7a,
+	0x00, 0x65, 0x60, 0x42,
+	0x20, 0xa0, 0x66, 0x7a,
X 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0xd2, 0x5b,
-	0xa0, 0x3d, 0x46, 0x62,
+	0x00, 0x65, 0xf2, 0x5b,
+	0xa0, 0x3d, 0x6e, 0x62,
X 	0x23, 0xa0, 0x0c, 0x08,
-	0x00, 0x65, 0xd2, 0x5b,
-	0xa0, 0x3d, 0x46, 0x62,
-	0x00, 0xb9, 0x3a, 0x42,
-	0xff, 0x65, 0x3a, 0x62,
+	0x00, 0x65, 0xf2, 0x5b,
+	0xa0, 0x3d, 0x6e, 0x62,
+	0x00, 0xb9, 0x66, 0x42,
+	0xff, 0x65, 0x66, 0x62,
X 	0xa1, 0x6a, 0x22, 0x01,
X 	0xff, 0x6a, 0xd4, 0x08,
-	0x10, 0x51, 0x46, 0x72,
+	0x10, 0x51, 0x6e, 0x72,
X 	0x40, 0x6a, 0x18, 0x00,
X 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0xd2, 0x5b,
-	0xa0, 0x3d, 0x46, 0x62,
-	0x10, 0x3d, 0x06, 0x00,
-	0x00, 0x65, 0x0e, 0x42,
+	0x00, 0x65, 0xf2, 0x5b,
+	0xa0, 0x3d, 0x38, 0x72,
X 	0x40, 0x6a, 0x18, 0x00,
X 	0xff, 0x34, 0xa6, 0x08,
-	0x80, 0x34, 0x4e, 0x62,
+	0x80, 0x34, 0x76, 0x62,
X 	0x7f, 0xa0, 0x40, 0x09,
X 	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0x18, 0x41,
-	0x64, 0x6a, 0x12, 0x5b,
-	0x80, 0x64, 0xbe, 0x6a,
-	0x04, 0x64, 0xa4, 0x72,
-	0x02, 0x64, 0xaa, 0x72,
-	0x00, 0x6a, 0x6c, 0x72,
-	0x03, 0x64, 0xba, 0x72,
-	0x01, 0x64, 0xa0, 0x72,
-	0x07, 0x64, 0x00, 0x73,
-	0x08, 0x64, 0x68, 0x72,
+	0x00, 0x65, 0x22, 0x41,
+	0x64, 0x6a, 0x3a, 0x5b,
+	0x80, 0x64, 0xea, 0x6a,
+	0x04, 0x64, 0xcc, 0x72,
+	0x02, 0x64, 0xd2, 0x72,
+	0x00, 0x6a, 0x94, 0x72,
+	0x03, 0x64, 0xe6, 0x72,
+	0x01, 0x64, 0xc8, 0x72,
+	0x07, 0x64, 0x28, 0x73,
+	0x08, 0x64, 0x90, 0x72,
X 	0x11, 0x6a, 0x22, 0x01,
-	0x07, 0x6a, 0x04, 0x5b,
+	0x07, 0x6a, 0x2c, 0x5b,
X 	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0x18, 0x41,
-	0xff, 0xa8, 0x70, 0x6a,
-	0xff, 0xa2, 0x88, 0x7a,
+	0x00, 0x65, 0x22, 0x41,
+	0xff, 0xa8, 0x98, 0x6a,
+	0xff, 0xa2, 0xb0, 0x7a,
X 	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0xfe, 0x5b,
-	0xff, 0xa2, 0x88, 0x7a,
+	0x00, 0xb9, 0x1e, 0x5c,
+	0xff, 0xa2, 0xb0, 0x7a,
X 	0x71, 0x6a, 0x22, 0x01,
X 	0xff, 0x6a, 0xd4, 0x08,
-	0x40, 0x51, 0x88, 0x62,
+	0x40, 0x51, 0xb0, 0x62,
X 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0xfe, 0x5b,
+	0x00, 0xb9, 0x1e, 0x5c,
X 	0xff, 0x3e, 0x74, 0x09,
X 	0xff, 0x90, 0x7c, 0x08,
-	0x00, 0x65, 0x44, 0x58,
-	0x00, 0x65, 0x2a, 0x41,
-	0x20, 0xa0, 0x90, 0x6a,
+	0x00, 0x65, 0x50, 0x58,
+	0x00, 0x65, 0x34, 0x41,
+	0x20, 0xa0, 0xb8, 0x6a,
X 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0xa8, 0x5b,
-	0xff, 0x6a, 0xbe, 0x5b,
+	0x00, 0x6a, 0xc8, 0x5b,
+	0xff, 0x6a, 0xde, 0x5b,
X 	0xff, 0xf8, 0xc8, 0x08,
X 	0xff, 0x4f, 0xc8, 0x08,
-	0x01, 0x6a, 0xa8, 0x5b,
-	0x00, 0xb9, 0xbe, 0x5b,
+	0x01, 0x6a, 0xc8, 0x5b,
+	0x00, 0xb9, 0xde, 0x5b,
X 	0x01, 0x4f, 0x9e, 0x18,
X 	0x02, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x6c, 0x5c,
-	0x00, 0x65, 0x2a, 0x41,
+	0x00, 0x65, 0x8c, 0x5c,
+	0x00, 0x65, 0x34, 0x41,
X 	0x41, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x18, 0x41,
+	0x00, 0x65, 0x22, 0x41,
X 	0x04, 0xa0, 0x40, 0x01,
-	0x00, 0x65, 0x84, 0x5c,
-	0x00, 0x65, 0x2a, 0x41,
-	0x10, 0x36, 0x68, 0x7a,
-	0xff, 0x38, 0x46, 0x09,
-	0xa4, 0x6a, 0xcc, 0x00,
-	0x39, 0x6a, 0xe6, 0x5b,
+	0x00, 0x65, 0xa4, 0x5c,
+	0x00, 0x65, 0x34, 0x41,
+	0x10, 0x36, 0x90, 0x7a,
+	0x05, 0x38, 0x46, 0x31,
+	0x04, 0x14, 0x58, 0x31,
+	0x03, 0xa9, 0x60, 0x31,
+	0xa3, 0x6a, 0xcc, 0x00,
+	0x38, 0x6a, 0x04, 0x5c,
X 	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xe6, 0x5b,
-	0xa9, 0x6a, 0xe8, 0x5b,
-	0x00, 0x65, 0x68, 0x42,
+	0x14, 0x6a, 0x06, 0x5c,
+	0xa9, 0x6a, 0x08, 0x5c,
+	0x00, 0x65, 0x90, 0x42,
X 	0xef, 0x36, 0x6c, 0x08,
-	0x00, 0x65, 0x68, 0x42,
+	0x00, 0x65, 0x90, 0x42,
X 	0x0f, 0x64, 0xc8, 0x08,
X 	0x07, 0x64, 0xc8, 0x08,
X 	0x00, 0x37, 0x6e, 0x00,
-	0x00, 0x65, 0x78, 0x5b,
-	0xff, 0x51, 0xce, 0x72,
-	0x20, 0x36, 0xde, 0x7a,
-	0x00, 0x90, 0x5c, 0x5b,
-	0x00, 0x65, 0xe0, 0x42,
+	0xff, 0x6a, 0xa4, 0x00,
+	0x00, 0x65, 0x98, 0x5b,
+	0xff, 0x51, 0xfc, 0x72,
+	0x20, 0x36, 0x06, 0x7b,
+	0x00, 0x90, 0x86, 0x5b,
+	0x00, 0x65, 0x08, 0x43,
X 	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0xd2, 0x5b,
-	0xe0, 0x3d, 0xfa, 0x62,
-	0x20, 0x12, 0xfa, 0x62,
-	0x51, 0x6a, 0x08, 0x5b,
-	0xff, 0x51, 0x20, 0x09,
-	0x20, 0xa0, 0xfa, 0x7a,
-	0x00, 0x90, 0x5c, 0x5b,
-	0x00, 0x65, 0x56, 0x5b,
+	0x00, 0x65, 0xf2, 0x5b,
+	0xe0, 0x3d, 0x22, 0x63,
+	0x20, 0x12, 0x22, 0x63,
+	0x51, 0x6a, 0x30, 0x5b,
+	0x00, 0x65, 0x80, 0x5b,
X 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0xa1, 0xf2, 0x62,
-	0x04, 0xa0, 0xf2, 0x7a,
+	0x00, 0xa1, 0x1a, 0x63,
+	0x04, 0xa0, 0x1a, 0x7b,
X 	0xfb, 0xa0, 0x40, 0x09,
X 	0x80, 0x36, 0x6c, 0x00,
-	0x80, 0xa0, 0x68, 0x7a,
+	0x80, 0xa0, 0x90, 0x7a,
X 	0x7f, 0xa0, 0x40, 0x09,
-	0xff, 0x6a, 0x04, 0x5b,
-	0x00, 0x65, 0x68, 0x42,
-	0x04, 0xa0, 0xf8, 0x7a,
-	0x00, 0x65, 0x84, 0x5c,
-	0x00, 0x65, 0xfa, 0x42,
-	0x00, 0x65, 0x6c, 0x5c,
+	0xff, 0x6a, 0x2c, 0x5b,
+	0x00, 0x65, 0x90, 0x42,
+	0x04, 0xa0, 0x20, 0x7b,
+	0x00, 0x65, 0xa4, 0x5c,
+	0x00, 0x65, 0x22, 0x43,
+	0x00, 0x65, 0x8c, 0x5c,
X 	0x31, 0x6a, 0x22, 0x01,
-	0x0c, 0x6a, 0x04, 0x5b,
-	0x00, 0x65, 0x68, 0x42,
+	0x0c, 0x6a, 0x2c, 0x5b,
+	0x00, 0x65, 0x90, 0x42,
X 	0x61, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x68, 0x42,
+	0x00, 0x65, 0x90, 0x42,
X 	0x10, 0x3d, 0x06, 0x00,
X 	0xff, 0x65, 0x68, 0x0c,
X 	0xff, 0x06, 0xd4, 0x08,
-	0x01, 0x0c, 0x0a, 0x7b,
-	0x04, 0x0c, 0x0a, 0x6b,
+	0x01, 0x0c, 0x32, 0x7b,
+	0x04, 0x0c, 0x32, 0x6b,
X 	0xe0, 0x03, 0x7a, 0x08,
-	0xe0, 0x3d, 0x1e, 0x63,
+	0xe0, 0x3d, 0x46, 0x63,
X 	0xff, 0x65, 0xcc, 0x08,
X 	0xff, 0x12, 0xda, 0x0c,
X 	0xff, 0x06, 0xd4, 0x0c,
X 	0xff, 0x65, 0x0c, 0x08,
-	0x02, 0x0b, 0x1a, 0x7b,
+	0x02, 0x0b, 0x42, 0x7b,
X 	0xff, 0x6a, 0xd4, 0x0c,
X 	0xd1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x18, 0x41,
+	0x00, 0x65, 0x22, 0x41,
X 	0xff, 0x65, 0x26, 0x09,
-	0x01, 0x0b, 0x32, 0x6b,
-	0x10, 0x0c, 0x24, 0x7b,
-	0x04, 0x0b, 0x2c, 0x6b,
+	0x01, 0x0b, 0x5a, 0x6b,
+	0x10, 0x0c, 0x4c, 0x7b,
+	0x04, 0x0b, 0x54, 0x6b,
X 	0xff, 0x6a, 0xca, 0x08,
-	0x04, 0x93, 0x30, 0x6b,
-	0x01, 0x94, 0x2e, 0x7b,
-	0x10, 0x94, 0x30, 0x6b,
+	0x04, 0x93, 0x58, 0x6b,
+	0x01, 0x94, 0x56, 0x7b,
+	0x10, 0x94, 0x58, 0x6b,
X 	0xc7, 0x93, 0x26, 0x09,
X 	0xff, 0x99, 0xd4, 0x08,
-	0x08, 0x93, 0x34, 0x6b,
+	0x38, 0x93, 0x5c, 0x6b,
X 	0xff, 0x6a, 0xd4, 0x0c,
-	0x80, 0x36, 0x38, 0x6b,
+	0x80, 0x36, 0x60, 0x6b,
X 	0x21, 0x6a, 0x22, 0x05,
X 	0xff, 0x65, 0x20, 0x09,
-	0xff, 0x51, 0x46, 0x63,
+	0xff, 0x51, 0x6e, 0x63,
X 	0xff, 0x37, 0xc8, 0x08,
-	0xa1, 0x6a, 0x50, 0x43,
+	0xa1, 0x6a, 0x7a, 0x43,
X 	0xff, 0x51, 0xc8, 0x08,
-	0xb9, 0x6a, 0x50, 0x43,
-	0xff, 0xba, 0x54, 0x73,
+	0xb9, 0x6a, 0x7a, 0x43,
+	0xff, 0x90, 0xa4, 0x08,
+	0xff, 0xba, 0x7e, 0x73,
X 	0xff, 0xba, 0x20, 0x09,
X 	0xff, 0x65, 0xca, 0x18,
-	0x00, 0x6c, 0x4a, 0x63,
+	0x00, 0x6c, 0x72, 0x63,
X 	0xff, 0x90, 0xca, 0x0c,
X 	0xff, 0x6a, 0xca, 0x04,
-	0x20, 0x36, 0x72, 0x7b,
-	0x00, 0x90, 0x3e, 0x5b,
-	0xff, 0x65, 0x72, 0x73,
-	0xff, 0xba, 0x66, 0x73,
-	0xff, 0xbb, 0xcc, 0x08,
-	0xff, 0xba, 0x20, 0x09,
-	0xff, 0x66, 0x76, 0x09,
-	0xff, 0x65, 0x20, 0x09,
-	0xff, 0xbb, 0x70, 0x73,
+	0x20, 0x36, 0x92, 0x7b,
+	0x00, 0x90, 0x66, 0x5b,
+	0xff, 0x65, 0x92, 0x73,
+	0xff, 0x52, 0x90, 0x73,
X 	0xff, 0xba, 0xcc, 0x08,
-	0xff, 0xbb, 0x20, 0x09,
+	0xff, 0x52, 0x20, 0x09,
X 	0xff, 0x66, 0x74, 0x09,
X 	0xff, 0x65, 0x20, 0x0d,
X 	0xff, 0xba, 0x7e, 0x0c,
-	0x00, 0x6a, 0x72, 0x5c,
+	0x00, 0x6a, 0x92, 0x5c,
X 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x51, 0xfe, 0x43,
-	0xff, 0x3f, 0xcc, 0x73,
+	0x00, 0x51, 0x1e, 0x44,
+	0xff, 0x3f, 0xec, 0x73,
X 	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3f, 0x3e, 0x5b,
-	0xff, 0x65, 0xcc, 0x73,
+	0x00, 0x3f, 0x66, 0x5b,
+	0xff, 0x65, 0xec, 0x73,
X 	0x20, 0x36, 0x6c, 0x00,
-	0x20, 0xa0, 0x86, 0x6b,
+	0x20, 0xa0, 0xa6, 0x6b,
X 	0xff, 0xb9, 0xa2, 0x0c,
X 	0xff, 0x6a, 0xa2, 0x04,
X 	0xff, 0x65, 0xa4, 0x08,
X 	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xf2, 0x5b,
+	0x45, 0x6a, 0x12, 0x5c,
X 	0x01, 0x6a, 0xd0, 0x01,
X 	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0x92, 0x7b,
+	0x80, 0xeb, 0xb2, 0x7b,
X 	0x01, 0x6a, 0xd6, 0x01,
X 	0x01, 0xe9, 0xa4, 0x34,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xf2, 0x5b,
+	0x45, 0x6a, 0x12, 0x5c,
X 	0x01, 0x6a, 0x18, 0x01,
X 	0xff, 0x6a, 0x1a, 0x09,
X 	0xff, 0x6a, 0x1c, 0x09,
X 	0x0d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0x64, 0x5c,
+	0x00, 0x65, 0x84, 0x5c,
X 	0xff, 0x99, 0xa4, 0x0c,
X 	0xff, 0x65, 0xa4, 0x08,
X 	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xf2, 0x5b,
+	0x45, 0x6a, 0x12, 0x5c,
X 	0x01, 0x6a, 0xd0, 0x01,
X 	0x01, 0x6a, 0xdc, 0x05,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xf2, 0x5b,
+	0x45, 0x6a, 0x12, 0x5c,
X 	0x01, 0x6a, 0x18, 0x01,
X 	0xff, 0x6a, 0x1a, 0x09,
X 	0xff, 0x6a, 0x1c, 0x09,
X 	0x01, 0x6a, 0x26, 0x05,
X 	0x01, 0x65, 0xd8, 0x31,
X 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0xc2, 0x7b,
+	0x80, 0xee, 0xe2, 0x7b,
X 	0xff, 0x6a, 0xdc, 0x0d,
X 	0xff, 0x65, 0x32, 0x09,
X 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x64, 0x44,
+	0x00, 0x65, 0x84, 0x44,
X 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0x88, 0x5b,
+	0x00, 0x6a, 0xa8, 0x5b,
X 	0xff, 0x52, 0xa2, 0x0c,
-	0x01, 0x0c, 0xd2, 0x7b,
-	0x04, 0x0c, 0xd2, 0x6b,
-	0xe0, 0x03, 0x7a, 0x08,
-	0xff, 0x3d, 0x06, 0x0c,
+	0x01, 0x0c, 0xf2, 0x7b,
+	0x04, 0x0c, 0xf2, 0x6b,
+	0xe0, 0x03, 0x06, 0x08,
+	0xe0, 0x03, 0x7a, 0x0c,
X 	0xff, 0x8c, 0x10, 0x08,
X 	0xff, 0x8d, 0x12, 0x08,
X 	0xff, 0x8e, 0x14, 0x0c,
@@ -515,29 +531,29 @@
X 	0x00, 0x6c, 0xda, 0x24,
X 	0xff, 0x65, 0xc8, 0x08,
X 	0xe0, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0xee, 0x5b,
+	0x41, 0x6a, 0x0e, 0x5c,
X 	0xff, 0x90, 0xe2, 0x09,
X 	0x20, 0x6a, 0xd0, 0x01,
-	0x04, 0x35, 0x10, 0x7c,
+	0x04, 0x35, 0x30, 0x7c,
X 	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0x0c, 0x64,
-	0x00, 0x65, 0x1c, 0x44,
+	0xdc, 0xee, 0x2c, 0x64,
+	0x00, 0x65, 0x3c, 0x44,
X 	0x01, 0x6a, 0xdc, 0x01,
X 	0x20, 0xa0, 0xd8, 0x31,
X 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x16, 0x7c,
+	0x80, 0xee, 0x36, 0x7c,
X 	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0x1a, 0x64,
+	0xd8, 0xee, 0x3a, 0x64,
X 	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0x1e, 0x6c,
+	0x18, 0xee, 0x3e, 0x6c,
X 	0xff, 0x6a, 0xd4, 0x0c,
X 	0x88, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0xee, 0x5b,
+	0x41, 0x6a, 0x0e, 0x5c,
X 	0x20, 0x6a, 0x18, 0x01,
X 	0xff, 0x6a, 0x1a, 0x09,
X 	0xff, 0x6a, 0x1c, 0x09,
X 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x35, 0x48, 0x6c,
+	0x04, 0x35, 0x68, 0x6c,
X 	0xa0, 0x6a, 0xca, 0x00,
X 	0x20, 0x65, 0xc8, 0x18,
X 	0xff, 0x6c, 0x32, 0x09,
@@ -548,14 +564,14 @@
X 	0xff, 0x6c, 0x32, 0x09,
X 	0xff, 0x6c, 0x32, 0x09,
X 	0xff, 0x6c, 0x32, 0x09,
-	0x00, 0x65, 0x34, 0x64,
+	0x00, 0x65, 0x54, 0x64,
X 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x64, 0x5c,
-	0x04, 0x35, 0x38, 0x7b,
-	0xa0, 0x6a, 0x54, 0x5c,
-	0x00, 0x65, 0x56, 0x5c,
-	0x00, 0x65, 0x56, 0x5c,
-	0x00, 0x65, 0x56, 0x44,
+	0x00, 0x65, 0x84, 0x5c,
+	0x04, 0x35, 0x60, 0x7b,
+	0xa0, 0x6a, 0x74, 0x5c,
+	0x00, 0x65, 0x76, 0x5c,
+	0x00, 0x65, 0x76, 0x5c,
+	0x00, 0x65, 0x76, 0x44,
X 	0xff, 0x65, 0xcc, 0x08,
X 	0xff, 0x99, 0xda, 0x08,
X 	0xff, 0x99, 0xda, 0x08,
@@ -564,37 +580,40 @@
X 	0xff, 0x99, 0xda, 0x08,
X 	0xff, 0x99, 0xda, 0x08,
X 	0xff, 0x99, 0xda, 0x0c,
-	0x08, 0x94, 0x64, 0x7c,
+	0x08, 0x94, 0x84, 0x7c,
X 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x68, 0x6c,
+	0x08, 0x93, 0x88, 0x6c,
X 	0xff, 0x6a, 0xd4, 0x0c,
X 	0xff, 0x40, 0x74, 0x09,
X 	0xff, 0x90, 0x80, 0x08,
X 	0xff, 0x6a, 0x72, 0x05,
-	0xff, 0x40, 0x80, 0x64,
-	0xff, 0x3f, 0x78, 0x64,
+	0xff, 0x40, 0xa0, 0x64,
+	0xff, 0x3f, 0x98, 0x64,
X 	0xff, 0x6a, 0xca, 0x04,
X 	0xff, 0x3f, 0x20, 0x09,
X 	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0xfe, 0x5b,
-	0x00, 0x90, 0x5c, 0x43,
+	0x00, 0xb9, 0x1e, 0x5c,
+	0xff, 0xba, 0x7e, 0x0c,
X 	0xff, 0x40, 0x20, 0x09,
X 	0xff, 0xba, 0x80, 0x0c,
-	0xff, 0x6a, 0x76, 0x01,
X 	0xff, 0x3f, 0x74, 0x09,
-	0xff, 0x90, 0x7e, 0x08,
-	0xff, 0xba, 0x38, 0x73,
-	0xff, 0xba, 0x20, 0x09,
-	0xff, 0x3f, 0x76, 0x09,
-	0xff, 0x3f, 0x20, 0x0d,
+	0xff, 0x90, 0x7e, 0x0c,
X };
X 
+static int aic7xxx_patch13_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch13_func(struct aic7xxx_host *p)
+{
+	return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
+}
+
X static int aic7xxx_patch12_func(struct aic7xxx_host *p);
X 
X static int
X aic7xxx_patch12_func(struct aic7xxx_host *p)
X {
-	return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
+	return ((p->features & AHC_CMD_CHAN) == 0);
X }
X 
X static int aic7xxx_patch11_func(struct aic7xxx_host *p);
@@ -699,71 +718,81 @@
X 			skip_instr :10,
X 			skip_patch :12;
X } sequencer_patches[] = {
-	{ aic7xxx_patch1_func, 1, 1, 2 },
-	{ aic7xxx_patch0_func, 2, 1, 1 },
-	{ aic7xxx_patch2_func, 3, 2, 1 },
-	{ aic7xxx_patch3_func, 7, 1, 1 },
+	{ aic7xxx_patch1_func, 2, 1, 2 },
+	{ aic7xxx_patch0_func, 3, 1, 1 },
+	{ aic7xxx_patch2_func, 4, 2, 1 },
X 	{ aic7xxx_patch3_func, 8, 1, 1 },
-	{ aic7xxx_patch4_func, 11, 4, 1 },
-	{ aic7xxx_patch5_func, 16, 3, 2 },
-	{ aic7xxx_patch0_func, 19, 4, 1 },
-	{ aic7xxx_patch6_func, 23, 1, 1 },
-	{ aic7xxx_patch7_func, 26, 1, 1 },
-	{ aic7xxx_patch4_func, 34, 4, 1 },
-	{ aic7xxx_patch8_func, 38, 3, 2 },
-	{ aic7xxx_patch0_func, 41, 3, 1 },
-	{ aic7xxx_patch9_func, 47, 7, 1 },
-	{ aic7xxx_patch4_func, 55, 3, 1 },
-	{ aic7xxx_patch8_func, 58, 2, 1 },
-	{ aic7xxx_patch1_func, 63, 60, 1 },
-	{ aic7xxx_patch8_func, 164, 1, 2 },
-	{ aic7xxx_patch0_func, 165, 1, 1 },
-	{ aic7xxx_patch2_func, 169, 1, 1 },
-	{ aic7xxx_patch2_func, 172, 1, 2 },
-	{ aic7xxx_patch0_func, 173, 2, 1 },
-	{ aic7xxx_patch10_func, 175, 1, 1 },
-	{ aic7xxx_patch8_func, 182, 1, 2 },
-	{ aic7xxx_patch0_func, 183, 3, 1 },
-	{ aic7xxx_patch8_func, 187, 1, 2 },
-	{ aic7xxx_patch0_func, 188, 1, 1 },
-	{ aic7xxx_patch8_func, 189, 7, 2 },
-	{ aic7xxx_patch0_func, 196, 1, 1 },
-	{ aic7xxx_patch2_func, 201, 13, 2 },
-	{ aic7xxx_patch0_func, 214, 8, 1 },
-	{ aic7xxx_patch10_func, 222, 1, 1 },
-	{ aic7xxx_patch8_func, 227, 1, 1 },
-	{ aic7xxx_patch8_func, 228, 1, 1 },
-	{ aic7xxx_patch8_func, 233, 1, 1 },
-	{ aic7xxx_patch8_func, 235, 2, 1 },
-	{ aic7xxx_patch8_func, 240, 8, 1 },
-	{ aic7xxx_patch8_func, 249, 1, 1 },
-	{ aic7xxx_patch2_func, 250, 2, 2 },
-	{ aic7xxx_patch0_func, 252, 4, 1 },
-	{ aic7xxx_patch10_func, 256, 2, 2 },
-	{ aic7xxx_patch0_func, 258, 1, 1 },
-	{ aic7xxx_patch11_func, 265, 1, 2 },
-	{ aic7xxx_patch0_func, 266, 1, 1 },
-	{ aic7xxx_patch5_func, 328, 1, 2 },
-	{ aic7xxx_patch0_func, 329, 1, 1 },
-	{ aic7xxx_patch3_func, 332, 1, 1 },
-	{ aic7xxx_patch11_func, 351, 1, 2 },
-	{ aic7xxx_patch0_func, 352, 1, 1 },
-	{ aic7xxx_patch6_func, 356, 1, 1 },
-	{ aic7xxx_patch7_func, 364, 3, 2 },
-	{ aic7xxx_patch0_func, 367, 1, 1 },
-	{ aic7xxx_patch1_func, 396, 3, 1 },
-	{ aic7xxx_patch10_func, 410, 1, 1 },
-	{ aic7xxx_patch2_func, 453, 7, 2 },
-	{ aic7xxx_patch0_func, 460, 8, 1 },
-	{ aic7xxx_patch2_func, 469, 4, 2 },
-	{ aic7xxx_patch0_func, 473, 6, 1 },
-	{ aic7xxx_patch2_func, 479, 4, 2 },
-	{ aic7xxx_patch0_func, 483, 3, 1 },
-	{ aic7xxx_patch2_func, 512, 17, 4 },
-	{ aic7xxx_patch12_func, 520, 4, 2 },
-	{ aic7xxx_patch0_func, 524, 2, 1 },
-	{ aic7xxx_patch0_func, 529, 33, 1 },
-	{ aic7xxx_patch6_func, 566, 2, 1 },
-	{ aic7xxx_patch6_func, 569, 9, 1 },
+	{ aic7xxx_patch3_func, 9, 1, 1 },
+	{ aic7xxx_patch4_func, 12, 4, 1 },
+	{ aic7xxx_patch5_func, 17, 3, 2 },
+	{ aic7xxx_patch0_func, 20, 4, 1 },
+	{ aic7xxx_patch6_func, 24, 1, 1 },
+	{ aic7xxx_patch7_func, 27, 1, 1 },
+	{ aic7xxx_patch2_func, 30, 1, 2 },
+	{ aic7xxx_patch0_func, 31, 3, 1 },
+	{ aic7xxx_patch4_func, 40, 4, 1 },
+	{ aic7xxx_patch8_func, 44, 3, 2 },
+	{ aic7xxx_patch0_func, 47, 3, 1 },
+	{ aic7xxx_patch9_func, 52, 7, 1 },
+	{ aic7xxx_patch4_func, 60, 3, 1 },
+	{ aic7xxx_patch8_func, 63, 2, 1 },
+	{ aic7xxx_patch1_func, 68, 60, 1 },
+	{ aic7xxx_patch8_func, 162, 1, 2 },
+	{ aic7xxx_patch0_func, 163, 2, 1 },
+	{ aic7xxx_patch2_func, 167, 2, 3 },
+	{ aic7xxx_patch8_func, 167, 1, 1 },
+	{ aic7xxx_patch0_func, 169, 2, 1 },
+	{ aic7xxx_patch8_func, 172, 1, 2 },
+	{ aic7xxx_patch0_func, 173, 1, 1 },
+	{ aic7xxx_patch2_func, 177, 1, 1 },
+	{ aic7xxx_patch2_func, 180, 3, 2 },
+	{ aic7xxx_patch0_func, 183, 5, 1 },
+	{ aic7xxx_patch2_func, 191, 2, 3 },
+	{ aic7xxx_patch8_func, 191, 1, 1 },
+	{ aic7xxx_patch0_func, 193, 3, 1 },
+	{ aic7xxx_patch10_func, 196, 2, 1 },
+	{ aic7xxx_patch8_func, 198, 7, 2 },
+	{ aic7xxx_patch0_func, 205, 1, 1 },
+	{ aic7xxx_patch2_func, 210, 14, 3 },
+	{ aic7xxx_patch10_func, 223, 1, 1 },
+	{ aic7xxx_patch0_func, 224, 9, 1 },
+	{ aic7xxx_patch8_func, 238, 2, 1 },
+	{ aic7xxx_patch8_func, 240, 1, 1 },
+	{ aic7xxx_patch10_func, 241, 6, 3 },
+	{ aic7xxx_patch2_func, 241, 2, 2 },
+	{ aic7xxx_patch0_func, 243, 4, 1 },
+	{ aic7xxx_patch8_func, 248, 1, 1 },
+	{ aic7xxx_patch8_func, 252, 11, 1 },
+	{ aic7xxx_patch2_func, 264, 3, 3 },
+	{ aic7xxx_patch10_func, 266, 1, 1 },
+	{ aic7xxx_patch0_func, 267, 5, 1 },
+	{ aic7xxx_patch10_func, 272, 1, 2 },
+	{ aic7xxx_patch0_func, 273, 7, 1 },
+	{ aic7xxx_patch11_func, 287, 1, 2 },
+	{ aic7xxx_patch0_func, 288, 1, 1 },
+	{ aic7xxx_patch5_func, 348, 1, 2 },
+	{ aic7xxx_patch0_func, 349, 1, 1 },
+	{ aic7xxx_patch3_func, 352, 1, 1 },
+	{ aic7xxx_patch2_func, 362, 3, 2 },
+	{ aic7xxx_patch0_func, 365, 5, 1 },
+	{ aic7xxx_patch11_func, 373, 1, 2 },
+	{ aic7xxx_patch0_func, 374, 1, 1 },
+	{ aic7xxx_patch6_func, 379, 1, 1 },
+	{ aic7xxx_patch1_func, 416, 3, 1 },
+	{ aic7xxx_patch10_func, 421, 11, 1 },
+	{ aic7xxx_patch2_func, 469, 7, 2 },
+	{ aic7xxx_patch0_func, 476, 8, 1 },
+	{ aic7xxx_patch2_func, 485, 4, 2 },
+	{ aic7xxx_patch0_func, 489, 6, 1 },
+	{ aic7xxx_patch2_func, 495, 4, 2 },
+	{ aic7xxx_patch0_func, 499, 3, 1 },
+	{ aic7xxx_patch12_func, 509, 10, 1 },
+	{ aic7xxx_patch2_func, 528, 17, 4 },
+	{ aic7xxx_patch13_func, 536, 4, 2 },
+	{ aic7xxx_patch0_func, 540, 2, 1 },
+	{ aic7xxx_patch0_func, 545, 33, 1 },
+	{ aic7xxx_patch12_func, 578, 4, 1 },
+	{ aic7xxx_patch6_func, 582, 2, 1 },
+	{ aic7xxx_patch6_func, 585, 9, 1 },
X 
X };
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.2.9/linux/drivers/scsi/scsi.c	Tue May 11 13:10:30 1999
+++ linux/drivers/scsi/scsi.c	Mon Jun  7 10:53:03 1999
@@ -109,6 +109,7 @@
X #define BLIST_SINGLELUN 0x10
X #define BLIST_NOTQ	0x20
X #define BLIST_SPARSELUN 0x40
+#define BLIST_MAX5LUN	0x80
X 
X /*
X  * Data declarations.
@@ -262,6 +263,7 @@
X {"HP", "C1790A", "", BLIST_NOLUN},              /* scanjet iip */
X {"HP", "C2500A", "", BLIST_NOLUN},              /* scanjet iicx */
X {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},	/* extra reset */
+{"RELISYS", "Scorpio", "*", BLIST_NOLUN},	/* responds to all LUN */
X 
X /*
X  * Other types of devices that have special flags.
@@ -273,6 +275,7 @@
X {"INSITE","I325VM","*", BLIST_KEY},
X {"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN},
X {"NRC","MBR-7.4","*", BLIST_FORCELUN | BLIST_SINGLELUN},
+{"REGAL","CDC-4X","*", BLIST_MAX5LUN | BLIST_SINGLELUN},
X {"NAKAMICH","MJ-4.8S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
X {"NAKAMICH","MJ-5.16S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
X {"PIONEER","CD-ROM DRM-600","*", BLIST_FORCELUN | BLIST_SINGLELUN},
@@ -932,6 +935,15 @@
X     *max_dev_lun = 8;
X     return 1;
X   }
+
+  /*
+   * REGAL CDC-4X: avoid hang after LUN 4
+   */
+  if (bflags & BLIST_MAX5LUN) {
+    *max_dev_lun = 5;
+    return 1;
+  }
+
X   /*
X    * We assume the device can't handle lun!=0 if: - it reports scsi-0 (ANSI
X    * SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it reports scsi-1
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.2.9/linux/drivers/scsi/scsi.h	Tue Mar 23 14:35:48 1999
+++ linux/drivers/scsi/scsi.h	Wed Jun  9 16:59:34 1999
@@ -296,6 +296,7 @@
X #define SCSI_1          1
X #define SCSI_1_CCS      2
X #define SCSI_2          3
+#define SCSI_3          4
X 
X /*
X  *  Every SCSI command starts with a one byte OP-code.
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v2.2.9/linux/drivers/scsi/scsi_proc.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/scsi_proc.c	Wed Jun  9 16:59:34 1999
@@ -298,7 +298,7 @@
X 		     scd->type < MAX_SCSI_DEVICE_CODE ? 
X 		     scsi_device_types[(int)scd->type] : "Unknown          " );
X     y += sprintf(buffer + len + y, "               ANSI"
-		     " SCSI revision: %02x", (scd->scsi_level < 3)?1:2);
+		     " SCSI revision: %02x", (scd->scsi_level - 1)?scd->scsi_level - 1:1);
X     if (scd->scsi_level == 2)
X 	y += sprintf(buffer + len + y, " CCS\n");
X     else
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.2.9/linux/drivers/scsi/scsi_syms.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/scsi_syms.c	Wed Jun  9 16:59:34 1999
@@ -27,13 +27,11 @@
X #include "constants.h"
X 
X #include "sd.h"
+#include <scsi/scsicam.h>
X /*
X  * This source file contains the symbol table used by scsi loadable
X  * modules.
X  */
-extern int scsicam_bios_param (Disk * disk,
-                               int dev,	int *ip	); 
-
X 
X extern void print_command (unsigned char *command);
X extern void print_sense(const char * devclass, Scsi_Cmnd * SCpnt);
@@ -47,6 +45,7 @@
X EXPORT_SYMBOL(scsi_register);
X EXPORT_SYMBOL(scsi_unregister);
X EXPORT_SYMBOL(scsicam_bios_param);
+EXPORT_SYMBOL(scsi_partsize);
X EXPORT_SYMBOL(scsi_allocate_device);
X EXPORT_SYMBOL(scsi_do_cmd);
X EXPORT_SYMBOL(scsi_command_size);
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/scsicam.c linux/drivers/scsi/scsicam.c
--- v2.2.9/linux/drivers/scsi/scsicam.c	Thu Nov 12 16:21:21 1998
+++ linux/drivers/scsi/scsicam.c	Wed Jun  9 16:59:34 1999
@@ -21,9 +21,8 @@
X #include "scsi.h"
X #include "hosts.h"
X #include "sd.h"
+#include <scsi/scsicam.h>
X 
-static int partsize(struct buffer_head *bh, unsigned long capacity,
-    unsigned int  *cyls, unsigned int *hds, unsigned int *secs);
X static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
X     unsigned int *secs);
X 
@@ -51,7 +50,7 @@
X 	return -1;
X 
X     /* try to infer mapping from partition table */
-    ret_code = partsize (bh, (unsigned long) size, (unsigned int *) ip + 2, 
+    ret_code = scsi_partsize (bh, (unsigned long) size, (unsigned int *) ip + 2, 
X 	(unsigned int *) ip + 0, (unsigned int *) ip + 1);
X     brelse (bh);
X 
@@ -80,7 +79,7 @@
X }
X 
X /*
- * Function : static int partsize(struct buffer_head *bh, unsigned long 
+ * Function : static int scsi_partsize(struct buffer_head *bh, unsigned long 
X  *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
X  *
X  * Purpose : to determine the BIOS mapping used to create the partition
@@ -90,7 +89,7 @@
X  *
X  */
X 
-static int partsize(struct buffer_head *bh, unsigned long capacity,
+int scsi_partsize(struct buffer_head *bh, unsigned long capacity,
X     unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
X     struct partition *p, *largest = NULL;
X     int i, largest_cyl;
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.2.9/linux/drivers/scsi/sd.c	Tue May 11 13:10:30 1999
+++ linux/drivers/scsi/sd.c	Mon Jun  7 16:51:01 1999
@@ -1729,7 +1729,7 @@
X static void sd_detach(Scsi_Device * SDp)
X {
X     Scsi_Disk * dpnt;
-    int i;
+    int i, j;
X     int max_p;
X     int start;
X 
@@ -1741,8 +1741,8 @@
X 	    max_p = sd_gendisk.max_p;
X 	    start = i << sd_gendisk.minor_shift;
X 
-	    for (i=max_p - 1; i >=0 ; i--) {
-		int index = start+i;
+	    for (j=max_p - 1; j >=0 ; j--) {
+		int index = start+j;
X 		kdev_t devi = MKDEV_SD_PARTITION(index);
X                 struct super_block *sb = get_super(devi);
X 		sync_dev(devi);
@@ -1759,7 +1759,7 @@
X 	    SDp->attached--;
X 	    sd_template.dev_noticed--;
X 	    sd_template.nr_dev--;
-	    SD_GENDISK(start).nr_real--;
+	    SD_GENDISK(i).nr_real--;
X 	    return;
X 	}
X     return;
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.2.9/linux/drivers/scsi/sg.c	Tue May 11 13:10:30 1999
+++ linux/drivers/scsi/sg.c	Mon Jun  7 16:27:06 1999
@@ -16,12 +16,10 @@
X  *
X  *  Borrows code from st driver. Thanks to Alessandro Rubini's "dd" book.
X  */
- static char * sg_version_str = "Version: 2.1.32 (990501)";
+ static char * sg_version_str = "Version: 2.1.34 (990603)";
+ static int sg_version_num = 20134; /* 2 digits for each component */
X /*
- *  D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au)
- *      - scatter list logic replaces previous large atomic SG_BIG_BUFF
- *        sized allocation. See notes in <scsi/sg.h> include file. 
- * 
+ *  D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au), notes:
X  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
X  *        the kernel/module needs to be built with CONFIG_SCSI_LOGGING
X  *        (otherwise the macros compile to empty statements), then do
@@ -34,13 +32,27 @@
X  *        Should use hlcomplete but it is too "noisy" (sd uses it).
X  *
X  *      - This driver obtains memory (heap) for the low-level driver to
- *        transfer/dma to and from. It is obtained from up to 4 sources:
- *              - 1 SG_SCATTER_SZ sized buffer on open() (per fd)
- *                [could be less if SG_SCATTER_SZ bytes not available]
- *              - obtain heap as required on write()s (get_free_pages)
+ *        transfer/dma to and from. It is obtained from up to 3 sources:
+ *              - obtain heap via get_free_pages()
X  *              - obtain heap from the shared scsi dma pool
X  *              - obtain heap from kernel directly (kmalloc) [last choice]
- *        the 'alt_address' field in the scatter_list structure and the
+ *        Each open() attempts to obtain a "reserve" buffer of
+ *        SG_DEF_RESERVED_SIZE bytes (or 0 bytes if opened O_RDONLY). The
+ *        amount actually obtained [which could be 0 bytes] can be found from
+ *        the SG_GET_RESERVED_SIZE ioctl(). This reserved buffer size can
+ *        be changed by calling the SG_SET_RESERVED_SIZE ioctl(). Since this
+ *        is an ambit claim, it should be followed by a SG_GET_RESERVED_SIZE
+ *        ioctl() to find out how much was actually obtained.
+ *        A subsequent write() to this file descriptor will use the
+ *        reserved buffer unless:
+ *              - it is already in use (eg during command queuing)
+ *              - or the write() needs a buffer size larger than the
+ *                reserved size
+ *        In these cases the write() will attempt to get the required memory
+ *        for the duration of this request but, if memory is low, it may
+ *        fail with ENOMEM.
+ *
+ *      - The 'alt_address' field in the scatter_list structure and the
X  *        related 'mem_src' indicate the source of the heap allocation.
X  *
X  */
@@ -67,11 +79,11 @@
X #include <scsi/sg.h>
X 
X 
-int sg_big_buff = SG_SCATTER_SZ;  /* sg_big_buff is ro through sysctl */
+int sg_big_buff = SG_DEF_RESERVED_SIZE; /* sg_big_buff is ro through sysctl */
X /* N.B. This global is here to keep existing software happy. It now holds
-   the size of the "first buffer" of the most recent sucessful sg_open(). 
+   the size of the reserve buffer of the most recent sucessful sg_open(). 
X    Only available when 'sg' compiled into kernel (rather than a module). 
-   This should probably be deprecated (use SG_GET_RESERVED_SIZE instead). */
+   This is deprecated (use SG_GET_RESERVED_SIZE ioctl() instead). */
X 
X #define SG_SECTOR_SZ 512
X #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
@@ -89,7 +101,6 @@
X static int sg_num_page = 0;
X #endif
X 
-#define SG_HEAP_FB 0    /* heap obtained at open() (one buffer per fd) */
X #define SG_HEAP_PAGE 1  /* heap from kernel via get_free_pages() */
X #define SG_HEAP_KMAL 2  /* heap from kernel via kmalloc() */
X #define SG_HEAP_POOL 3  /* heap from scsi dma pool (mid-level) */
@@ -112,9 +123,9 @@
X {
X     unsigned short use_sg;      /* Number of pieces of scatter-gather */
X     unsigned short sglist_len;  /* size of malloc'd scatter-gather list */
-    unsigned bufflen;           /* Size of data buffer */
+    unsigned bufflen;           /* Size of (aggregate) data buffer */
X     unsigned b_malloc_len;      /* actual len malloc'ed in buffer */
-    void * buffer;              /* Data buffer or scatter list (12 bytes) */
+    void * buffer;              /* Data buffer or scatter list,12 bytes each*/
X     char mem_src;               /* heap whereabouts of 'buffer' */
X } Sg_scatter_hold;    /* 20 bytes long on i386 */
X 
@@ -126,10 +137,10 @@
X     Scsi_Cmnd * my_cmdp;        /* NULL -> ready to read, else id */
X     struct sg_request * nextrp; /* NULL -> tail request (slist) */
X     struct sg_fd * parentfp;    /* NULL -> not in use */
-    Sg_scatter_hold data;       /* hold buffers, perhaps scatter list */
-    struct sg_header header;    /* scsi command+info <include/sg.h> */
-    char fb_used;               /* 1 -> using fst_buf, normally 0 (used) */
-} Sg_request; /* around 72 bytes long on i386 */
+    Sg_scatter_hold data;       /* hold buffer, perhaps scatter list */
+    struct sg_header header;    /* scsi command+info, see <scsi/sg.h> */
+    char res_used;              /* 1 -> using reserve buffer, 0 -> not ... */
+} Sg_request; /* 72 bytes long on i386 */
X 
X typedef struct sg_fd /* holds the state of a file descriptor */
X {
@@ -137,41 +148,52 @@
X     struct sg_device * parentdp;     /* owning device */
X     struct wait_queue * read_wait;   /* queue read until command done */
X     int timeout;                     /* defaults to SG_DEFAULT_TIMEOUT */
-    char * fst_buf;     /* try to grab SG_SCATTER_SZ sized buffer on open */
-    int fb_size;        /* actual size of allocated fst_buf */
-    Sg_request * headrp; /* head of request slist, NULL->empty */
+    Sg_scatter_hold reserve;  /* buffer held for this file descriptor */
+    unsigned save_scat_len;   /* original length of trunc. scat. element */
+    Sg_request * headrp;      /* head of request slist, NULL->empty */
X     struct fasync_struct * async_qp; /* used by asynchronous notification */
X     Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */
-    char low_dma;       /* as in parent but possible overridden to 1 */
+    char low_dma;       /* as in parent but possibly overridden to 1 */
X     char force_packid;  /* 1 -> pack_id input to read(), 0 -> ignored */
X     char closed;        /* 1 -> fd closed but request(s) outstanding */
-    char my_mem_src;    /* heap whereabouts of this sg_fb object */
+    char my_mem_src;    /* heap whereabouts of this Sg_fd object */
X     char cmd_q;         /* 1 -> allow command queuing, 0 -> don't */
X     char underrun_flag; /* 1 -> flag underruns, 0 -> don't, 2 -> test */
-} Sg_fd; /* around 1192 bytes long on i386 */
+    char next_cmd_len;  /* 0 -> automatic (def), >0 -> use on next write() */
+} Sg_fd; /* 1208 bytes long on i386 */
X 
X typedef struct sg_device /* holds the state of each scsi generic device */
X {
X     Scsi_Device * device;
-    struct wait_queue * generic_wait;/* queue open if O_EXCL on prev. open */
+    struct wait_queue * o_excl_wait; /* queue open() when O_EXCL in use */
X     int sg_tablesize;   /* adapter's max scatter-gather table size */
X     Sg_fd * headfp;     /* first open fd belonging to this device */
X     kdev_t i_rdev;      /* holds device major+minor number */
X     char exclude;       /* opened for exclusive access */
X     char sgdebug;       /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
-    unsigned char merge_fd; /* 0->sequencing per fd (def) else fd count */
-} Sg_device; /* around 24 bytes long on i386 */
+    unsigned char merge_fd; /* 0->sequencing per fd, else fd count */
+} Sg_device; /* 24 bytes long on i386 */
X 
X 
X static int sg_fasync(int fd, struct file * filp, int mode);
X static void sg_command_done(Scsi_Cmnd * SCpnt);
-static int sg_sc_build(Sg_request * srp, int max_buff_size,
-                       const char * inp, int num_write_xfer);
-static int sg_sc_undo_rem(Sg_request * srp, char * outp,
-                          int num_read_xfer);
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 14'
echo 'File patch-2.2.10 is continued in part 15'
echo 15 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 15 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 15; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
-static char * sg_malloc(Sg_request * srp, int size, int * retSzp, 
+static int sg_start_req(Sg_request * srp, int max_buff_size,
+                        const char * inp, int num_write_xfer);
+static void sg_finish_rem_req(Sg_request * srp, char * outp,
+                              int num_read_xfer);
+static int sg_build_scat(Sg_scatter_hold * schp, int buff_size, 
+                         const Sg_fd * sfp);
+static void sg_write_xfer(Sg_scatter_hold * schp, const char * inp, 
+                          int num_write_xfer);
+static void sg_remove_scat(Sg_scatter_hold * schp);
+static void sg_read_xfer(Sg_scatter_hold * schp, char * outp,
+                         int num_read_xfer);
+static void sg_build_reserve(Sg_fd * sfp, int req_size);
+static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
+static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
+static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp, 
X                         int * mem_srcp);
-static void sg_free(Sg_request * srp, char * buff, int size, int mem_src);
+static void sg_free(char * buff, int size, int mem_src);
X static char * sg_low_malloc(int rqSz, int lowDma, int mem_src, 
X                             int * retSzp);
X static void sg_low_free(char * buff, int size, int mem_src);
@@ -180,7 +202,7 @@
X static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id);
X static Sg_request * sg_add_request(Sg_fd * sfp);
X static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp);
-static int sg_fb_in_use(const Sg_fd * sfp);
+static int sg_res_in_use(const Sg_fd * sfp);
X static void sg_clr_scpnt(Scsi_Cmnd * SCpnt);
X static void sg_shorten_timeout(Scsi_Cmnd * scpnt);
X static void sg_debug(const Sg_device * sdp, const Sg_fd * sfp, int part_of);
@@ -197,6 +219,7 @@
X     int flags = filp->f_flags;
X     Sg_device * sdp;
X     Sg_fd * sfp;
+    int res;
X 
X     if ((NULL == sg_dev_arr) || (dev < 0) || (dev >= sg_template.dev_max))
X         return -ENXIO;
@@ -207,38 +230,35 @@
X         printk("sg_open: inode maj=%d, min=%d   sdp maj=%d, min=%d\n",
X                MAJOR(inode->i_rdev), MINOR(inode->i_rdev),
X                MAJOR(sdp->i_rdev), MINOR(sdp->i_rdev));
+    /* 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.  */
X     if(! scsi_block_when_processing_errors(sdp->device))
X         return -ENXIO;
-/*  if (O_RDWR != (flags & O_ACCMODE)) */
-/*      return -EACCES;   May just want to get to a ioctl, so remove */
X 
X     SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
-   /* If we want exclusive access, then wait until the device is not
-    * busy, and then set the flag to prevent anyone else from using it. */
+
X     if (flags & O_EXCL) {
X         if (O_RDONLY == (flags & O_ACCMODE))
X             return -EACCES;   /* Can't lock it with read only access */
-        while (sdp->headfp) {
-            if (flags & O_NONBLOCK)
-                return -EBUSY;
-            interruptible_sleep_on(&sdp->generic_wait);
-            if (signal_pending(current))
-                return -ERESTARTSYS;
-        }
-        sdp->exclude = 1;
-    }
-    else { /* Wait until nobody has an exclusive open on this device. */
-        while (sdp->exclude) {
-            if (flags & O_NONBLOCK)
-                return -EBUSY;
-            interruptible_sleep_on(&sdp->generic_wait);
-            if (signal_pending(current))
-                return -ERESTARTSYS;
-        }
+        if (sdp->headfp && (filp->f_flags & O_NONBLOCK))
+            return -EBUSY;
+        res = 0;  /* following is a macro that beats race condition */
+        __wait_event_interruptible(sdp->o_excl_wait, 
+               ((sdp->headfp || sdp->exclude) ? 0 : (sdp->exclude = 1)), 
+                                   res);
+        if (res)
+            return res; /* -ERESTARTSYS because signal hit process */
+    }
+    else if (sdp->exclude) { /* some other fd has an exclusive lock on dev */
+        if (filp->f_flags & O_NONBLOCK)
+            return -EBUSY;
+        res = 0;  /* following is a macro that beats race condition */
+        __wait_event_interruptible(sdp->o_excl_wait, (! sdp->exclude), res);
+        if (res)
+            return res; /* -ERESTARTSYS because signal hit process */
X     }
-    /* OK, we should have grabbed the device.  Mark the thing so
-     * that other processes know that we have it, and initialize the
-     * state variables to known values. */
X     if (! sdp->headfp) { /* no existing opens on this device */
X         sdp->sgdebug = 0;
X         sdp->sg_tablesize = sdp->device->host->sg_tablesize;
@@ -284,16 +304,14 @@
X     if(sg_template.module)
X         __MOD_DEC_USE_COUNT(sg_template.module);
X     sdp->exclude = 0;
-    wake_up_interruptible(&sdp->generic_wait);
+    wake_up_interruptible(&sdp->o_excl_wait);
X     return 0;
X }
X 
-/* Read back the results of a SCSI command which was sent in a prior
-   write(). */
X static ssize_t sg_read(struct file * filp, char * buf,
X                        size_t count, loff_t *ppos)
X {
-    int k;
+    int k, res;
X     Sg_device * sdp;
X     Sg_fd * sfp;
X     Sg_request * srp;
@@ -305,13 +323,8 @@
X     SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n", 
X                                MINOR(sdp->i_rdev), (int)count));
X     
-    /* 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.  */
X     if(! scsi_block_when_processing_errors(sdp->device))
X         return -ENXIO;
-
X     if (ppos != &filp->f_pos)
X         ; /* FIXME: Hmm.  Seek to the right place, or fail?  */
X     if ((k = verify_area(VERIFY_WRITE, buf, count)))
@@ -319,13 +332,15 @@
X     if (sfp->force_packid && (count >= size_sg_header))
X         req_pack_id = shp->pack_id;
X     srp = sg_get_request(sfp, req_pack_id);
-    while(! srp) {
+    if (! srp) { /* now wait on packet to arrive */
X         if (filp->f_flags & O_NONBLOCK)
X             return -EAGAIN;
-        interruptible_sleep_on(&sfp->read_wait);
-        if (signal_pending(current))
-            return -ERESTARTSYS;
-        srp = sg_get_request(sfp, req_pack_id);
+        res = 0;  /* following is a macro that beats race condition */
+        __wait_event_interruptible(sfp->read_wait, 
+                                   (srp = sg_get_request(sfp, req_pack_id)),
+                                   res);
+        if (res)
+            return res; /* -ERESTARTSYS because signal hit process */
X     }
X     if (2 != sfp->underrun_flag)
X         srp->header.pack_len = srp->header.reply_len;   /* Why ????? */
@@ -337,13 +352,13 @@
X         if (count > srp->header.reply_len)
X             count = srp->header.reply_len;
X         if (count > size_sg_header) /* release does copy_to_user */
-            sg_sc_undo_rem(srp, buf, count - size_sg_header);
+            sg_finish_rem_req(srp, buf, count - size_sg_header);
X         else
-            sg_sc_undo_rem(srp, NULL, 0);
+            sg_finish_rem_req(srp, NULL, 0);
X     }
X     else {
X         count = (srp->header.result == 0) ? 0 : -EIO;
-        sg_sc_undo_rem(srp, NULL, 0);
+        sg_finish_rem_req(srp, NULL, 0);
X     }
X     return count;
X }
@@ -366,22 +381,15 @@
X     SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n", 
X                                MINOR(sdp->i_rdev), (int)count));
X 
-/* 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.  */
X     if(! scsi_block_when_processing_errors(sdp->device) )
X         return -ENXIO;
-
X     if (ppos != &filp->f_pos)
X         ; /* FIXME: Hmm.  Seek to the right place, or fail?  */
X 
X     if ((k = verify_area(VERIFY_READ, buf, count)))
X         return k;  /* protects following copy_from_user()s + get_user()s */
-/* The minimum scsi command length is 6 bytes.  If we get anything
- * less than this, it is clearly bogus.  */
X     if (count < (size_sg_header + 6))
-        return -EIO;
+        return -EIO;   /* The minimum scsi command length is 6 bytes. */ 
X 
X     srp = sg_add_request(sfp);
X     if (! srp) {
@@ -392,55 +400,54 @@
X     buf += size_sg_header;
X     srp->header.pack_len = count;
X     __get_user(opcode, buf);
-    cmd_size = COMMAND_SIZE(opcode);
-    if ((opcode >= 0xc0) && srp->header.twelve_byte) 
-        cmd_size = 12;
+    if (sfp->next_cmd_len > 0) {
+        if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {
+            SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));
+            sfp->next_cmd_len = 0;
+            return -EDOM;
+        }
+        cmd_size = sfp->next_cmd_len;
+        sfp->next_cmd_len = 0; /* reset so only this write() effected */
+    }
+    else {
+        cmd_size = COMMAND_SIZE(opcode); /* based on SCSI command group */
+        if ((opcode >= 0xc0) && srp->header.twelve_byte) 
+            cmd_size = 12;
+    }
X     SCSI_LOG_TIMEOUT(4, printk("sg_write:   scsi opcode=0x%02x, cmd_size=%d\n", 
X                                (int)opcode, cmd_size));
X /* Determine buffer size.  */
X     input_size = count - cmd_size;
X     mxsize = (input_size > srp->header.reply_len) ? input_size :
X                                                     srp->header.reply_len;
-/* Don't include the command header itself in the size.  */
X     mxsize -= size_sg_header;
X     input_size -= size_sg_header;
-/* Verify user has actually passed enough bytes for this command. */
X     if (input_size < 0) {
-        sg_sc_undo_rem(srp, NULL, 0);
-        return -EIO; 
+        sg_remove_request(sfp, srp);
+        return -EIO; /* User did not pass enough bytes for this command. */
X     }
-
-/* If we cannot allocate the buffer, report an error. */
-    if ((k = sg_sc_build(srp, mxsize, buf + cmd_size, input_size))) {
+    if ((k = sg_start_req(srp, mxsize, buf + cmd_size, input_size))) {
X         SCSI_LOG_TIMEOUT(1, printk("sg_write: build err=%d\n", k));
-        sg_sc_undo_rem(srp, NULL, 0);
-        return k;
+        sg_finish_rem_req(srp, NULL, 0);
+        return k;    /* probably out of space --> ENOMEM */
X     }
-
X /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: allocating device\n")); */
-/* Grab a command pointer for the device we want to talk to. If we
- * don't want to block, just return with the appropriate message.  */
X     if (! (SCpnt = scsi_allocate_device(NULL, sdp->device, 
X                                         !(filp->f_flags & O_NONBLOCK)))) {
-        sg_sc_undo_rem(srp, NULL, 0);
-        return -EAGAIN;
+        sg_finish_rem_req(srp, NULL, 0);
+        return -EAGAIN;   /* No available command blocks at the moment */
X     }
X /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: device allocated\n")); */
-
X     srp->my_cmdp = SCpnt;
X     SCpnt->request.rq_dev = sdp->i_rdev;
X     SCpnt->request.rq_status = RQ_ACTIVE;
X     SCpnt->sense_buffer[0] = 0;
X     SCpnt->cmd_len = cmd_size;
-    /* Now copy the SCSI command from the user's address space.  */
X     __copy_from_user(cmnd, buf, cmd_size);
-
-/* Set the LUN field in the command structure.  */
+/* Set the LUN field in the command structure, overriding user input  */
X     cmnd[1]= (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
+
X /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: do cmd\n")); */
-/* 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.  */
X     spin_lock_irqsave(&io_request_lock, flags);
X     SCpnt->use_sg = srp->data.use_sg;
X     SCpnt->sglist_len = srp->data.sglist_len;
@@ -454,6 +461,8 @@
X     srp->data.sglist_len = 0;
X     srp->data.bufflen = 0;
X     srp->data.buffer = NULL;
+/* Now send everything of to mid-level. The next time we hear about this
+   packet is when sg_command_done() is called (ie a callback). */
X     scsi_do_cmd(SCpnt, (void *)cmnd,
X                 (void *)SCpnt->buffer, mxsize,
X                 sg_command_done, sfp->timeout, SG_DEFAULT_RETRIES);
@@ -475,9 +484,6 @@
X         return -ENXIO;
X     SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n", 
X                                MINOR(sdp->i_rdev), (int)cmd_in));
-     /* If we are in the middle of error recovery, then don't allow any
-     *  access to this device.  Also, error recovery *may* have taken the
-     *  device offline, in which case all further access is prohibited.  */
X     if(! scsi_block_when_processing_errors(sdp->device) )
X         return -ENXIO;
X 
@@ -485,20 +491,18 @@
X     {
X     case SG_SET_TIMEOUT:
X         return get_user(sfp->timeout, (int *)arg);
-    case SG_GET_TIMEOUT:
+    case SG_GET_TIMEOUT:  /* N.B. User receives timeout as return value */
X         return sfp->timeout; /* strange ..., for backward compatibility */
X     case SG_SET_FORCE_LOW_DMA:
X         result = get_user(val, (int *)arg);
X         if (result) return result;
X         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);
-            }
X             sfp->low_dma = 1;
-            if (! sfp->fst_buf)
-                return -ENOMEM;
+            if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
+                val = (int)sfp->reserve.bufflen;
+                sg_remove_scat(&sfp->reserve);
+                sg_build_reserve(sfp, val);
+            }
X         }
X         else
X             sfp->low_dma = sdp->device->host->unchecked_isa_dma;
@@ -550,15 +554,20 @@
X     case SG_GET_SG_TABLESIZE:
X         return put_user(sdp->sg_tablesize, (int *)arg);
X     case SG_SET_RESERVED_SIZE:
-        /* currently ignored, future extension */
X         if (O_RDWR != (filp->f_flags & O_ACCMODE))
X             return -EACCES;
X         result = get_user(val, (int *)arg);
X         if (result) return result;
-        /* logic should go here */
+        if (val != sfp->reserve.bufflen) {
+            if (sg_res_in_use(sfp))
+                return -EBUSY;
+            sg_remove_scat(&sfp->reserve);
+            sg_build_reserve(sfp, val);
+        }
X         return 0;
X     case SG_GET_RESERVED_SIZE:
-        return put_user(sfp->fb_size, (int *)arg);
+        val = (int)sfp->reserve.bufflen;
+        return put_user(val, (int *)arg);
X     case SG_GET_MERGE_FD:
X         return put_user((int)sdp->merge_fd, (int *)arg);
X     case SG_SET_MERGE_FD:
@@ -587,6 +596,13 @@
X         return 0;
X     case SG_GET_UNDERRUN_FLAG:
X         return put_user((int)sfp->underrun_flag, (int *)arg);
+    case SG_NEXT_CMD_LEN:
+        result = get_user(val, (int *)arg);
+        if (result) return result;
+        sfp->next_cmd_len = (val > 0) ? val : 0;
+        return 0;
+    case SG_GET_VERSION_NUM:
+        return put_user(sg_version_num, (int *)arg);
X     case SG_EMULATED_HOST:
X         return put_user(sdp->device->host->hostt->emulated, (int *)arg);
X     case SCSI_IOCTL_SEND_COMMAND:
@@ -594,8 +610,7 @@
X            user already has read/write access to the generic device and so
X            can execute arbitrary SCSI commands.  */
X         if (O_RDWR != (filp->f_flags & O_ACCMODE))
-            return -EACCES; /* require write access since these could be
-                               dangerous */
+            return -EACCES; /* very dangerous things can be done here */
X         return scsi_ioctl_send_command(sdp->device, (void *)arg);
X     case SG_SET_DEBUG:
X         result = get_user(val, (int *)arg);
@@ -613,8 +628,7 @@
X         return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
X     default:
X         if (O_RDWR != (filp->f_flags & O_ACCMODE))
-            return -EACCES; /* require write access since these could be
-                               dangerous */
+            return -EACCES; /* don't know so take safe approach */
X         return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
X     }
X }
@@ -664,8 +678,7 @@
X }
X 
X /* This function is called by the interrupt handler when we
- * actually have a command that is complete.  Change the
- * flags to indicate that we have a result.  */
+ * actually have a command that is complete. */
X static void sg_command_done(Scsi_Cmnd * SCpnt)
X {
X     int dev = MINOR(SCpnt->request.rq_dev);
@@ -712,17 +725,16 @@
X     sg_clr_scpnt(SCpnt);
X     srp->my_cmdp = NULL;
X 
-    SCSI_LOG_TIMEOUT(4, 
-              printk("sg__done: dev=%d, scsi_stat=%d, res=0x%x\n", 
+    SCSI_LOG_TIMEOUT(4, printk("sg__done: dev=%d, scsi_stat=%d, res=0x%x\n", 
X                 dev, (int)status_byte(SCpnt->result), (int)SCpnt->result));
-/* See if the command completed normally, or whether something went wrong. */
X     memcpy(srp->header.sense_buffer, SCpnt->sense_buffer,
X            sizeof(SCpnt->sense_buffer));
X     switch (host_byte(SCpnt->result)) 
-    {
+    { /* This setup of 'result' is for backward compatibility and is best
+         ignored by the user who should use target, host + driver status */
X     case DID_OK:
-    case DID_PASSTHROUGH: /* just guessing */
-    case DID_SOFT_ERROR:  /* just guessing */
+    case DID_PASSTHROUGH: 
+    case DID_SOFT_ERROR:
X       srp->header.result = 0;
X       break;
X     case DID_NO_CONNECT:
@@ -738,12 +750,6 @@
X       srp->header.result = EIO;
X       break;
X     case DID_ERROR:
-      /* There really should be DID_UNDERRUN and DID_OVERRUN error values,
-       * and a means for callers of scsi_do_cmd to indicate whether an
-       * underrun or overrun should signal an error.  Until that can be
-       * implemented, this kludge allows for returning useful error values
-       * except in cases that return DID_ERROR that might be due to an
-       * underrun. */
X       if (SCpnt->sense_buffer[0] == 0 &&
X           status_byte(SCpnt->result) == GOOD)
X           srp->header.result = 0;
@@ -767,8 +773,6 @@
X /* filesystems using this device. */
X         sdp->device->changed = 1;
X     }
-
-/* Pick up error and status information */
X     srp->header.target_status = status_byte(SCpnt->result);
X     if ((sdp->sgdebug > 0) && 
X         ((CHECK_CONDITION == srp->header.target_status) ||
@@ -784,15 +788,14 @@
X         SCSI_LOG_TIMEOUT(1,
X                printk("sg__done: already closed, freeing ...\n"));
X /* should check if module is unloaded <<<<<<< */
-        sg_sc_undo_rem(srp, NULL, 0);
+        sg_finish_rem_req(srp, NULL, 0);
X         if (NULL == sfp->headrp) { 
X             SCSI_LOG_TIMEOUT(1,
X                 printk("sg__done: already closed, final cleanup\n"));
X             sg_remove_sfp(sdp, sfp);
X         }
X     }
-/* Now wake up the process that is waiting for the result. */
-    /* A. Rubini says this is preferable+faster than wake_up() */
+/* Now wake up any sg_read() that is waiting for this packet. */
X     wake_up_interruptible(&sfp->read_wait);
X     if ((sfp->async_qp) && (! closed))
X         kill_fasync(sfp->async_qp, SIGPOLL);
@@ -873,17 +876,20 @@
X             printk("  *** Following data belongs to invoking FD ***\n");
X         else if (! fp->parentdp)
X             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, urun_flag=%d, closed=%d\n",
-               (int)fp->low_dma, (int)fp->force_packid, 
-               (int)fp->underrun_flag, (int)fp->closed);
+        printk("   FD(%d): timeout=%d, bufflen=%d, use_sg=%d\n",
+               k, fp->timeout, fp->reserve.bufflen, (int)fp->reserve.use_sg);
+        printk("   low_dma=%d, cmd_q=%d, s_sc_len=%d, f_packid=%d\n",
+               (int)fp->low_dma, (int)fp->cmd_q, (int)fp->save_scat_len,
+               (int)fp->force_packid);
+        printk("   urun_flag=%d, next_cmd_len=%d, closed=%d\n",
+               (int)fp->underrun_flag, (int)fp->next_cmd_len, 
+               (int)fp->closed);
X         srp = fp->headrp;
X         if (NULL == srp)
X             printk("     No requests active\n");
X         while (srp) {
-            if (srp->fb_used)
-                printk("using 1st buff >> ");
+            if (srp->res_used)
+                printk("reserved buff >> ");
X             else
X                 printk("     ");
X             if (srp->my_cmdp)
@@ -988,7 +994,7 @@
X 
X     SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k));
X     sdp->device = scsidp;
-    sdp->generic_wait = NULL;
+    sdp->o_excl_wait = NULL;
X     sdp->headfp= NULL;
X     sdp->exclude = 0;
X     sdp->merge_fd = 0;  /* Cope with SG_DEF_MERGE_FD on open */
@@ -1041,10 +1047,8 @@
X         }
X         scsidp->attached--;
X         sg_template.nr_dev--;
-        /*
-         * avoid associated device /dev/sg? bying incremented
-         * each time module is inserted/removed , <d...@lectra.fr>
-         */
+/* avoid associated device /dev/sg? being incremented
+ * each time module is inserted/removed , <d...@lectra.fr> */
X         sg_template.dev_noticed--;
X         return;
X     }
@@ -1099,42 +1103,80 @@
X #endif
X }
X 
-static int sg_sc_build(Sg_request * srp, int max_buff_size,
-                       const char * inp, int num_write_xfer)
+static int sg_start_req(Sg_request * srp, int max_buff_size,
+                        const char * inp, int num_write_xfer)
+{
+    int res;
+    Sg_fd * sfp = srp->parentfp;
+    Sg_scatter_hold * req_schp = &srp->data;
+    Sg_scatter_hold * rsv_schp = &sfp->reserve;
+
+    SCSI_LOG_TIMEOUT(4, printk("sg_start_req: max_buff_size=%d\n", 
+                               max_buff_size)); 
+    if ((! sg_res_in_use(sfp)) && (max_buff_size <= rsv_schp->bufflen)) {
+        sg_link_reserve(sfp, srp, max_buff_size);
+        sg_write_xfer(req_schp, inp, num_write_xfer);
+    }
+    else {
+        res = sg_build_scat(req_schp, max_buff_size, sfp);
+        if (res) {
+            sg_remove_scat(req_schp);
+            return res;
+        }
+        sg_write_xfer(req_schp, inp, num_write_xfer);
+    }
+    return 0;
+}
+
+static void sg_finish_rem_req(Sg_request * srp, char * outp, 
+                              int num_read_xfer)
+{
+    Sg_fd * sfp = srp->parentfp;
+    Sg_scatter_hold * req_schp = &srp->data;
+
+    SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n",
+                               (int)srp->res_used)); 
+    if (num_read_xfer > 0)
+        sg_read_xfer(req_schp, outp, num_read_xfer);
+    if (srp->res_used)
+        sg_unlink_reserve(sfp, srp);
+    else 
+        sg_remove_scat(req_schp);
+    sg_remove_request(sfp, srp);
+}
+
+static int sg_build_scat(Sg_scatter_hold * schp, int buff_size, 
+                         const Sg_fd * sfp)
X {
X     int ret_sz, mem_src;
-    int blk_size = max_buff_size;
+    int blk_size = buff_size;
X     char * p = NULL;
X 
-    if ((blk_size < 0) || (! srp))
+    if ((blk_size < 0) || (! sfp))
X         return -EFAULT;
-    
-    SCSI_LOG_TIMEOUT(4, printk("sg_sc_build: m_b_s=%d, num_write_xfer=%d\n", 
-                                  max_buff_size, num_write_xfer)); 
X     if (0 == blk_size)
X         ++blk_size;             /* don't know why */
X /* round request up to next highest SG_SECTOR_SZ byte boundary */
X     blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
-    SCSI_LOG_TIMEOUT(5, printk("sg_sc_build: blk_size=%d\n", blk_size));
-
+    SCSI_LOG_TIMEOUT(4, printk("sg_build_scat: buff_size=%d, blk_size=%d\n",
+                               buff_size, blk_size));
X     if (blk_size <= SG_SCATTER_SZ) {
-        mem_src = SG_HEAP_FB;
-        p = sg_malloc(srp, blk_size, &ret_sz, &mem_src);
+        mem_src = SG_HEAP_PAGE;
+        p = sg_malloc(sfp, blk_size, &ret_sz, &mem_src);
X         if (! p)
X             return -ENOMEM;
X         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);
+            schp->use_sg = 0;
+            schp->buffer = p;
+            schp->bufflen = blk_size;
+            schp->mem_src = mem_src;
+            schp->b_malloc_len = blk_size;
X             return 0;
X         }
X     }
X     else {
X         mem_src = SG_HEAP_PAGE;
-        p = sg_malloc(srp, SG_SCATTER_SZ, &ret_sz, &mem_src);
+        p = sg_malloc(sfp, SG_SCATTER_SZ, &ret_sz, &mem_src);
X         if (! p)
X             return -ENOMEM;
X     }
@@ -1144,23 +1186,23 @@
X         int k, rem_sz, num, nxt;
X         int sc_bufflen = PAGE_SIZE;
X         int mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
-        int sg_tablesize = srp->parentfp->parentdp->sg_tablesize;
+        int sg_tablesize = sfp->parentdp->sg_tablesize;
X         int first = 1;
X 
X         k = SG_HEAP_KMAL;  /* want to protect mem_src, use k as scratch */
-        srp->data.buffer = (struct scatterlist *)sg_malloc(srp, 
+        schp->buffer = (struct scatterlist *)sg_malloc(sfp, 
X                                 sc_bufflen, &num, &k);
-        srp->data.mem_src = (char)k;
+        schp->mem_src = (char)k;
X         /* N.B. ret_sz and mem_src carried into this block ... */
-        if (! srp->data.buffer)
+        if (! schp->buffer)
X             return -ENOMEM;
X         else if (num != sc_bufflen) {
X             sc_bufflen = num;
X             mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
X         }
-        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; 
+        schp->sglist_len = sc_bufflen;
+        memset(schp->buffer, 0, sc_bufflen);
+        for (k = 0, sclp = schp->buffer, rem_sz = blk_size, nxt =0; 
X              (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems); 
X              ++k, rem_sz -= ret_sz, ++sclp) {
X             if (first) 
@@ -1168,7 +1210,7 @@
X             else {
X                 num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
X                 mem_src = SG_HEAP_PAGE;
-                p = sg_malloc(srp, num, &ret_sz, &mem_src);
+                p = sg_malloc(sfp, num, &ret_sz, &mem_src);
X                 if (! p)
X                     break;
X             }
@@ -1176,73 +1218,188 @@
X             sclp->length = ret_sz;
X             sclp->alt_address = (char *)(long)mem_src;
X             
-            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;
-            }
X             SCSI_LOG_TIMEOUT(5, 
-                printk("sg_sc_build: k=%d, a=0x%p, len=%d, ms=%d\n", 
+                printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n", 
X                 k, sclp->address, ret_sz, mem_src));
X         } /* end of for loop */
-        srp->data.use_sg = k;
+        schp->use_sg = k;
X         SCSI_LOG_TIMEOUT(5, 
-            printk("sg_sc_build: use_sg=%d, rem_sz=%d\n", k, rem_sz));
-        srp->data.bufflen = blk_size;
+            printk("sg_build_scat: use_sg=%d, rem_sz=%d\n", k, rem_sz));
+        schp->bufflen = blk_size;
X         if (rem_sz > 0)   /* must have failed */
X             return -ENOMEM;
X     }
X     return 0;
X }
X 
-static int sg_sc_undo_rem(Sg_request * srp, char * outp,
-                          int num_read_xfer)
+static void sg_write_xfer(Sg_scatter_hold * schp, const char * inp, 
+                          int num_write_xfer)
X {
-    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;
-                }
+    SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_write_xfer=%d, use_sg=%d\n", 
+                               num_write_xfer, schp->use_sg)); 
+    if ((! inp) || (num_write_xfer <= 0))
+        return;
+    if (schp->use_sg > 0) {
+        int k, num;
+        struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+
+        for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) { 
+            num = (int)sclp->length;
+            if (num > num_write_xfer) {
+                __copy_from_user(sclp->address, inp, num_write_xfer);
+                break;
X             }
+            else {
+                __copy_from_user(sclp->address, inp, num);
+                num_write_xfer -= num;
+                if (num_write_xfer <= 0)
+                    break;
+                inp += num;
+            }
+        }
+    }
+    else
+        __copy_from_user(schp->buffer, inp, num_write_xfer);
+}
+
+static void sg_remove_scat(Sg_scatter_hold * schp)
+{
+    SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: use_sg=%d\n", schp->use_sg)); 
+    if(schp->use_sg > 0) {
+        int k, mem_src;
+        struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+
+        for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) {
X             mem_src = (int)(long)sclp->alt_address;
X             SCSI_LOG_TIMEOUT(5, 
-                printk("sg_sc_undo_rem: k=%d, a=0x%p, len=%d, ms=%d\n", 
+                printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n", 
X                        k, sclp->address, sclp->length, mem_src));
-            sg_free(srp, sclp->address, sclp->length, mem_src);
+            sg_free(sclp->address, sclp->length, mem_src);
+            sclp->address = NULL;
+            sclp->length = 0;
+        }
+        sg_free(schp->buffer, schp->sglist_len, schp->mem_src);
+    }
+    else if (schp->buffer)
+        sg_free(schp->buffer, schp->b_malloc_len, schp->mem_src);
+    schp->buffer = NULL;
+    schp->bufflen = 0;
+    schp->use_sg = 0;
+    schp->sglist_len = 0;
+}
+
+static void sg_read_xfer(Sg_scatter_hold * schp, char * outp,
+                         int num_read_xfer)
+{
+    SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_read_xfer=%d\n", 
+                               num_read_xfer)); 
+    if ((! outp) || (num_read_xfer <= 0))
+        return;
+    if(schp->use_sg > 0) {
+        int k, num;
+        struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+
+        for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) {
+            num = (int)sclp->length;
+            if (num > num_read_xfer) {
+                __copy_to_user(outp, sclp->address, num_read_xfer);
+                break;
+            }
+            else {
+                __copy_to_user(outp, sclp->address, num);
+                num_read_xfer -= num;
+                if (num_read_xfer <= 0)
+                    break;
+                outp += num;
+            }
X         }
-        sg_free(srp, srp->data.buffer, srp->data.sglist_len, 
-                srp->data.mem_src);
+    }
+    else
+        __copy_to_user(outp, schp->buffer, num_read_xfer);
+}
+
+static void sg_build_reserve(Sg_fd * sfp, int req_size)
+{
+    Sg_scatter_hold * schp = &sfp->reserve;
+
+    SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size)); 
+    do {
+        if (req_size < PAGE_SIZE)
+            req_size = PAGE_SIZE;
+        if (0 == sg_build_scat(schp, req_size, sfp))
+            return;
+        else
+            sg_remove_scat(schp);
+        req_size >>= 1; /* divide by 2 */
+    } while (req_size >  (PAGE_SIZE / 2));
+}
+
+static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
+{
+    Sg_scatter_hold * req_schp = &srp->data;
+    Sg_scatter_hold * rsv_schp = &sfp->reserve;
+
+    SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); 
+    if (rsv_schp->use_sg > 0) {
+        int k, num;
+        int rem = size;
+        struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
+
+        for (k = 0; k < rsv_schp->use_sg; ++k, ++sclp) {
+            num = (int)sclp->length;
+            if (rem <= num) {
+                sfp->save_scat_len = num;
+                sclp->length = (unsigned)rem;
+                break;
+            }
+            else
+                rem -= num;
+        }
+        if (k < rsv_schp->use_sg) {
+            req_schp->use_sg = k + 1;   /* adjust scatter list length */
+            req_schp->bufflen = size;
+            req_schp->sglist_len = rsv_schp->sglist_len;
+            req_schp->buffer = rsv_schp->buffer;
+            req_schp->mem_src = rsv_schp->mem_src;
+            req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+        }
+        else
+            SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n")); 
X     }
X     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=0x%p not found\n", 
-                                   srp));
+        req_schp->use_sg = 0;
+        req_schp->bufflen = size;
+        req_schp->buffer = rsv_schp->buffer;
+        req_schp->mem_src = rsv_schp->mem_src;
+        req_schp->use_sg = rsv_schp->use_sg;
+        req_schp->b_malloc_len = rsv_schp->b_malloc_len;
X     }
-    return 0;
+    srp->res_used = 1;
+}
+
+static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
+{
+    Sg_scatter_hold * req_schp = &srp->data;
+    Sg_scatter_hold * rsv_schp = &sfp->reserve;
+
+    SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->use_sg=%d\n",
+                               (int)req_schp->use_sg)); 
+    if (rsv_schp->use_sg > 0) {
+        struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
+
+        if (sfp->save_scat_len > 0) 
+            (sclp + (req_schp->use_sg - 1))->length = 
+                                        (unsigned)sfp->save_scat_len;
+        else
+            SCSI_LOG_TIMEOUT(1, printk(
+                        "sg_unlink_reserve: BAD save_scat_len\n")); 
+    }
+    req_schp->use_sg = 0;
+    req_schp->bufflen = 0;
+    req_schp->buffer = NULL;
+    req_schp->sglist_len = 0;
+    sfp->save_scat_len = 0;
+    srp->res_used = 0;
X }
X 
X static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id)
@@ -1292,7 +1449,7 @@
X     if (resp) {
X         resp->parentfp = sfp;
X         resp->nextrp = NULL;
-        resp->fb_used = 0;
+        resp->res_used = 0;
X         memset(&resp->data, 0, sizeof(Sg_scatter_hold));
X         memset(&resp->header, 0, sizeof(struct sg_header));
X         resp->my_cmdp = NULL;
@@ -1347,13 +1504,6 @@
X                    sdp->device->host->unchecked_isa_dma : 1;
X     sfp->cmd_q = SG_DEF_COMMAND_Q;
X     sfp->underrun_flag = SG_DEF_UNDERRUN_FLAG;
-    if (get_reserved)
-        sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, sfp->low_dma, 
-                                     SG_HEAP_PAGE, &sfp->fb_size);
-    else
-        sfp->fst_buf = NULL;
-    if (! sfp->fst_buf)
-        sfp->fb_size = 0;
X     sfp->parentdp = sdp;
X     if (! sdp->headfp)
X         sdp->headfp = sfp;
@@ -1363,11 +1513,14 @@
X            pfp = pfp->nextfp;
X         pfp->nextfp = sfp;
X     }
-    sg_big_buff = sfp->fb_size; /* show sysctl most recent "fb" size */
X     SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n",
X                                sfp, (int)sfp->my_mem_src));
-    SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   fb_sz=%d, fst_buf=0x%p\n",
-                               sfp->fb_size, sfp->fst_buf));
+    if (get_reserved) {
+        sg_build_reserve(sfp, SG_DEF_RESERVED_SIZE);
+        sg_big_buff = sfp->reserve.bufflen; /* sysctl shows most recent size */
+        SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, use_sg=%d\n",
+                               sfp->reserve.bufflen, sfp->reserve.use_sg));
+    }
X     return sfp;
X }
X 
@@ -1388,7 +1541,7 @@
X         while (srp) {
X             tsrp = srp->nextrp;
X             if (! srp->my_cmdp)
-                sg_sc_undo_rem(srp, NULL, 0);
+                sg_finish_rem_req(srp, NULL, 0);
X             else
X                 ++dirty;
X             srp = tsrp;
@@ -1409,12 +1562,12 @@
X                 prev_fp = fp;
X             }
X         }
-SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    fb_sz=%d, fst_buf=0x%p\n",
-                 sfp->fb_size, sfp->fst_buf));
-        sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
+        if (sfp->reserve.bufflen > 0) {
+SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    bufflen=%d, use_sg=%d\n",
+                 (int)sfp->reserve.bufflen, (int)sfp->reserve.use_sg));
+            sg_remove_scat(&sfp->reserve);
+        }
X         sfp->parentdp = NULL;
-        sfp->fst_buf = NULL;
-        sfp->fb_size = 0;
X     SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    sfp=0x%p\n", sfp));
X         sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->my_mem_src);
X         res = 1;
@@ -1427,12 +1580,12 @@
X     return res;
X }
X 
-static int sg_fb_in_use(const Sg_fd * sfp)
+static int sg_res_in_use(const Sg_fd * sfp)
X {
X     const Sg_request * srp = sfp->headrp;
X 
X     while (srp) {
-        if (srp->fb_used)
+        if (srp->res_used)
X             return 1;
X         srp = srp->nextrp;
X     }
@@ -1511,7 +1664,7 @@
X     return resp;
X }
X 
-static char * sg_malloc(Sg_request * srp, int size, int * retSzp, 
+static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp, 
X                         int * mem_srcp)
X {
X     char * resp = NULL;
@@ -1520,26 +1673,16 @@
X     if (size <= 0)
X         ;
X     else {
-        Sg_fd * sfp = srp->parentfp;
X         int low_dma = sfp->low_dma;
X         int l_ms = -1;  /* invalid value */
X 
X         switch (*mem_srcp) 
X         {
X         case SG_HEAP_PAGE:
-        case SG_HEAP_FB:
X             l_ms = (size < PAGE_SIZE) ? SG_HEAP_POOL : SG_HEAP_PAGE;
X             resp = sg_low_malloc(size, low_dma, l_ms, 0);
X             if (resp)
X                 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;
-            }
X             resp = sg_low_malloc(size, low_dma, l_ms, &size);
X             if (! resp) {
X                 l_ms = (SG_HEAP_POOL == l_ms) ? SG_HEAP_PAGE : SG_HEAP_POOL;
@@ -1595,18 +1738,12 @@
X                mem_src, buff, size);
X }
X 
-static void sg_free(Sg_request * srp, char * buff, int size, int mem_src)
+static void sg_free(char * buff, int size, int mem_src)
X {
-    Sg_fd * sfp = srp->parentfp;
-
X     SCSI_LOG_TIMEOUT(6, 
X         printk("sg_free: buff=0x%p, size=%d\n", buff, size));
-    if ((! sfp) || (! buff) || (size <= 0))
+    if ((! buff) || (size <= 0))
X         ;
-    else if (sfp->fst_buf == buff) {
-        srp->fb_used = 0;
-        SCSI_LOG_TIMEOUT(6, printk("sg_free:   left cause fst_buf\n"));
-    }
X     else
X         sg_low_free(buff, size, mem_src);
X }
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.2.9/linux/drivers/scsi/sr_ioctl.c	Tue May 11 13:10:30 1999
+++ linux/drivers/scsi/sr_ioctl.c	Fri May 14 16:04:16 1999
@@ -122,11 +122,9 @@
X             if (!quiet)
X 		printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL "
X 		       "REQUEST.\n", target);
-            if ((SCpnt->sense_buffer[12] == 0x20 ||
-	        SCpnt->sense_buffer[12] == 0x24) &&
+            if (SCpnt->sense_buffer[12] == 0x20 &&
X                 SCpnt->sense_buffer[13] == 0x00) {
X                 /* sense: Invalid command operation code */
-                /* or Invalid field in cdb */
X                 err = -EDRIVE_CANT_DO_THIS;
X             } else {
X                 err = -EINVAL;
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.2.9/linux/drivers/scsi/st.c	Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/st.c	Sat May 22 14:51:26 1999
@@ -11,7 +11,7 @@
X   Copyright 1992 - 1999 Kai Makisara
X 		 email Kai.Ma...@metla.fi
X 
-  Last modified: Sun Mar  7 09:03:17 1999 by makisara@home
+  Last modified: Tue May 18 09:29:52 1999 by makisara@home
X   Some small formal changes - aeb, 950809
X */
X 
@@ -164,8 +164,6 @@
X 	   SCpnt->request_bufflen);
X     if (driver_byte(result) & DRIVER_SENSE)
X       print_sense("st", SCpnt);
-    else
-      printk("\n");
X   }
X   else
X #endif
@@ -289,6 +287,7 @@
X   }
X   else
X       bp = (STp->buffer)->b_data;
+  SCpnt->cmd_len = 0;
X   SCpnt->request.sem = &(STp->sem);
X   SCpnt->request.rq_status = RQ_SCSI_BUSY;
X   SCpnt->request.rq_dev = STp->devt;
@@ -3380,7 +3379,6 @@
X 
X    tpnt->devt = MKDEV(SCSI_TAPE_MAJOR, i);
X    tpnt->dirty = 0;
-   tpnt->waiting = NULL;
X    tpnt->in_use = 0;
X    tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
X    tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/st.h linux/drivers/scsi/st.h
--- v2.2.9/linux/drivers/scsi/st.h	Wed Sep  9 14:51:09 1998
+++ linux/drivers/scsi/st.h	Sat May 22 14:51:26 1999
@@ -65,7 +65,6 @@
X typedef struct {
X   kdev_t devt;
X   unsigned capacity;
-  struct wait_queue * waiting;
X   Scsi_Device* device;
X   struct semaphore sem;
X   ST_buffer * buffer;
diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.2.9/linux/drivers/scsi/sym53c8xx.c	Fri Apr 16 14:47:31 1999
+++ linux/drivers/scsi/sym53c8xx.c	Sat May 22 13:42:53 1999
@@ -572,6 +572,8 @@
X #define remap_pci_mem(base, size)	((u_long) __va(base))
X #define unmap_pci_mem(vaddr, size)
X #define pcivtobus(p)			((p) & pci_dvma_mask)
+#elif defined(__alpha__)
+#define pcivtobus(p)			((p) & 0xfffffffful)
X #else	/* __sparc__ */
X #define pcivtobus(p)			(p)
X 
diff -u --recursive --new-file v2.2.9/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.2.9/linux/drivers/sound/es1370.c	Fri Apr 16 14:47:31 1999
+++ linux/drivers/sound/es1370.c	Sat May 22 13:05:43 1999
@@ -33,8 +33,8 @@
X  *            to make the card a four channel one: use dsp to output two
X  *            channels to LINE and dac to output the other two channels to
X  *            SPKR. Set the mixer to only output synth to SPKR.
- *   micz     it looks like this changes the MIC input impedance. I don't know
- *            any detail though.
+ *   micbias  sets the +5V bias to the mic if using an electretmic.
+ *            
X  *
X  *  Note: sync mode is not yet supported (i.e. running dsp and dac from the same
X  *  clock source)
@@ -92,6 +92,12 @@
X  *                     Alpha fixes reported by Peter Jones <pjo...@redhat.com>
X  *                     Note: joystick address handling might still be wrong on archs
X  *                     other than i386
+ *    10.05.99   0.21  Added support for an electret mic for SB PCI64
+ *                     to the Linux kernel sound driver. This mod also straighten
+ *                     out the question marks around the mic impedance setting
+ *                     (micz). From Kim....@fisub.mail.abb.com
+ *    11.05.99   0.22  Implemented the IMIX call to mute recording monitor.
+ *                     Guenter Geiger <gei...@epy.co.at>
X  *
X  * some important things missing in Ensoniq documentation:
X  *
@@ -107,8 +113,8 @@
X  * The card uses a 22.5792 MHz crystal.
X  * The LINEIN jack may be converted to an AOUT jack by
X  * setting pin 47 (XCTL0) of the ES1370 to high.
- * Pin 48 (XCTL1) of the ES1370 presumably changes the input impedance of the
- * MIC jack.
+ * Pin 48 (XCTL1) of the ES1370 sets the +5V bias for an electretmic
+ * 
X  *
X  */
X 
@@ -190,7 +196,7 @@
X #define DAC2_DIVTOSR(x) (1411200/((x)+2))
X 
X #define CTRL_ADC_STOP   0x80000000  /* 1 = ADC stopped */
-#define CTRL_XCTL1      0x40000000  /* ? mic impedance */
+#define CTRL_XCTL1      0x40000000  /* electret mic bias */
X #define CTRL_OPEN       0x20000000  /* no function, can be read and written */
X #define CTRL_PCLKDIV    0x1fff0000  /* ADC/DAC2 clock divider */
X #define CTRL_SH_PCLKDIV 16
@@ -301,6 +307,7 @@
X 		unsigned int recsrc;
X 		unsigned int modcnt;
X 		unsigned short micpreamp;
+	        unsigned int imix;
X 	} mix;
X 
X 	/* wave stuff */
@@ -839,7 +846,8 @@
X 			return put_user(s->mix.recsrc, (int *)arg);
X 			
X                 case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
-			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+			val = SOUND_MASK_IMIX;
+			for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
X 				if (mixtable[i].avail)
X 					val |= 1 << i;
X 			return put_user(val, (int *)arg);
@@ -858,6 +866,9 @@
X 			
X                 case SOUND_MIXER_CAPS:
X 			return put_user(0, (int *)arg);
+		
+		case SOUND_MIXER_IMIX:
+			return put_user(s->mix.imix, (int *)arg);
X 
X 		default:
X 			i = _IOC_NR(cmd);
@@ -870,6 +881,14 @@
X 		return -EINVAL;
X 	s->mix.modcnt++;
X 	switch (_IOC_NR(cmd)) {
+
+	case SOUND_MIXER_IMIX:
+		if (arg == 0) 
+			return -EFAULT;
+		get_user_ret(s->mix.imix,(int *)arg, -EFAULT);
+		val = s->mix.recsrc;
+		/* fall through */
+
X 	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
X 		get_user_ret(val, (int *)arg, -EFAULT);
X 		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
@@ -886,7 +905,10 @@
X 		wrcodec(s, 0x13, j & 0xaa);
X 		wrcodec(s, 0x14, (j >> 8) & 0x17);
X 		wrcodec(s, 0x15, (j >> 8) & 0x0f);
-		i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc30;
+		i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc60;
+		if (!s->mix.imix) {
+		     i &= 0xff60;  /* mute record and line monitor */
+		}
X 		wrcodec(s, 0x10, i);
X 		wrcodec(s, 0x11, i >> 8);
X 		return 0;
@@ -2262,7 +2284,7 @@
X static int joystick[NR_DEVICE] = { 0, };
X #endif
X static int lineout[NR_DEVICE] = { 0, };
-static int micz[NR_DEVICE] = { 0, };
+static int micbias[NR_DEVICE] = { 0, };
X 
X /* --------------------------------------------------------------------- */
X 
@@ -2295,7 +2317,7 @@
X 
X 	if (!pci_present())   /* No PCI bus in this machine! */
X 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.20 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.22 time " __TIME__ " " __DATE__ "\n");
X 	while (index < NR_DEVICE && 
X 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
X 		if (pcidev->base_address[0] == 0 || 
@@ -2328,8 +2350,10 @@
X 			goto err_irq;
X 		}
X 		/* initialize codec registers */
-		s->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
-		if (joystick[index]) {
+		/* note: setting CTRL_SERR_DIS is reported to break
+		 * mic bias setting (by Kim....@fisub.mail.abb.com) */
+	        s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
+	        if (joystick[index]) {
X 			if (check_region(0x200, JOY_EXTENT))
X 				printk(KERN_ERR "es1370: io port 0x200 in use\n");
X 			else
@@ -2337,7 +2361,7 @@
X 		}
X 		if (lineout[index])
X 			s->ctrl |= CTRL_XCTL0;
-		if (micz[index])
+		if (micbias[index])
X 			s->ctrl |= CTRL_XCTL1;
X 		s->sctrl = 0;
X 		printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
@@ -2361,6 +2385,7 @@
X 		wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!!  */
X 		wrcodec(s, 0x18, 0); /* recording source is mixer */
X 		wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */
+		s->mix.imix = 1;
X 		fs = get_fs();
X 		set_fs(KERNEL_DS);
X 		val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD;
@@ -2403,8 +2428,8 @@
X MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
X MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
X MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
-MODULE_PARM(micz, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(micz, "changes (??) the microphone impedance");
+MODULE_PARM(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone");
X 
X MODULE_AUTHOR("Thomas M. Sailer, sai...@ife.ee.ethz.ch, hb9...@hb9w.che.eu");
X MODULE_DESCRIPTION("ES1370 AudioPCI Driver");
diff -u --recursive --new-file v2.2.9/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.2.9/linux/drivers/sound/sound_core.c	Wed Mar 10 15:29:47 1999
+++ linux/drivers/sound/sound_core.c	Mon Jun  7 11:06:06 1999
@@ -52,6 +52,22 @@
X 	struct sound_unit *next;
X };
X 
+#ifdef CONFIG_SOUND_SONICVIBES
+extern int init_sonicvibes(void);
+#endif
+#ifdef CONFIG_SOUND_ES1370
+extern int init_es1370(void);
+#endif
+#ifdef CONFIG_SOUND_ES1371
+extern int init_es1371(void);
+#endif
+#ifdef CONFIG_SOUND_MSNDCLAS
+extern int msnd_classic_init(void);
+#endif
+#ifdef CONFIG_SOUND_MSNDPIN
+extern int msnd_pinnacle_init(void);
+#endif
+
X /*
X  *	Low level list operator. Scan the ordered list, find a hole and
X  *	join into it. Called with the lock asserted
@@ -132,7 +148,7 @@
X  *	This lock guards the sound loader list.
X  */
X 
-static spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
X 
X /*
X  *	Allocate the controlling structure and add it to the sound driver
diff -u --recursive --new-file v2.2.9/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.2.9/linux/drivers/video/cgsixfb.c	Tue Mar 23 14:35:48 1999
+++ linux/drivers/video/cgsixfb.c	Sat May 29 11:10:15 1999
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.16 1999/03/09 14:01:49 davem Exp $
+/* $Id: cgsixfb.c,v 1.16.2.1 1999/05/25 00:59:35 davem Exp $
X  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
X  *
X  * Copyright (C) 1996,1998 Jakub Jelinek (j...@ultra.linux.cz)
@@ -588,7 +588,7 @@
X 	p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
X }
X 
-static char idstring[60] __initdata = { 0 };
+static char idstring[70] __initdata = { 0 };
X 
X __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
X {
@@ -599,6 +599,7 @@
X 	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
X 	u32 conf;
X 	char *p;
+	char *cardtype;
X 	struct bt_regs *bt;
X 
X 	strcpy(fb->info.modename, "CGsix");
@@ -656,15 +657,29 @@
X 	case CG6_FHC_CPU_68020: p = "68020"; break;
X 	default: p = "i386"; break;
X 	}
+
+	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
+		if (fix->smem_len <= 0x100000) {
+			cardtype = "TurboGX";
+		} else {
+			cardtype = "TurboGX+";
+		}
+	} else {
+		if (fix->smem_len <= 0x100000) {
+			cardtype = "GX";
+		} else {
+			cardtype = "GX+";
+		}
+	}
X 	                                                                        
X 	sprintf(idstring, 
X #ifdef __sparc_v9__
-		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys, 
+		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, 
X #else	
-		    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, 
+		    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, 
X #endif
X 		    (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK,
-		    p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK);
+		    p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype);
X 		    
X 	cg6_reset(fb);
X 		    
diff -u --recursive --new-file v2.2.9/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.2.9/linux/drivers/video/fbcon.c	Wed Apr 28 11:37:30 1999
+++ linux/drivers/video/fbcon.c	Fri May 14 12:49:59 1999
@@ -2300,3 +2300,4 @@
X EXPORT_SYMBOL(fb_display);
X EXPORT_SYMBOL(fbcon_redraw_bmove);
X EXPORT_SYMBOL(fbcon_dummy);
+EXPORT_SYMBOL(fb_con);
diff -u --recursive --new-file v2.2.9/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c
--- v2.2.9/linux/drivers/video/mdacon.c	Wed Mar 10 15:29:48 1999
+++ linux/drivers/video/mdacon.c	Fri May 14 17:46:16 1999
@@ -597,7 +597,7 @@
X 	if (mda_first_vc > mda_last_vc)
X 		return;
X 
-	take_over_console(&mda_con, mda_first_vc, mda_last_vc, 0);
+	take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);
X }
X 
X #ifdef MODULE
diff -u --recursive --new-file v2.2.9/linux/fs/Config.in linux/fs/Config.in
--- v2.2.9/linux/fs/Config.in	Wed Mar 10 15:29:48 1999
+++ linux/fs/Config.in	Sun Jun 13 19:54:06 1999
@@ -69,9 +69,9 @@
X   fi
X   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X     tristate 'NFS server support' CONFIG_NFSD
-  fi
-  if [ "$CONFIG_NFSD" != "n" ]; then
-    bool '   Emulate SUN NFS server' CONFIG_NFSD_SUN
+    if [ "$CONFIG_NFSD" != "n" ]; then
+      bool '   Emulate SUN NFS server' CONFIG_NFSD_SUN
+    fi
X   fi
X   if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
X     define_bool CONFIG_SUNRPC y
@@ -86,9 +86,6 @@
X     fi
X   fi
X   tristate 'SMB filesystem support (to mount WfW shares etc.)' CONFIG_SMB_FS
-  if [ "$CONFIG_SMB_FS" != "n" ]; then
-    bool 'SMB Win95 bug work-around' CONFIG_SMB_WIN95
-  fi
X fi
X if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
X   tristate 'NCP filesystem support (to mount NetWare volumes)' CONFIG_NCP_FS
diff -u --recursive --new-file v2.2.9/linux/fs/adfs/dir.c linux/fs/adfs/dir.c
--- v2.2.9/linux/fs/adfs/dir.c	Thu May 13 23:10:30 1999
+++ linux/fs/adfs/dir.c	Thu May 13 23:25:58 1999
@@ -138,9 +138,6 @@
X 	struct super_block *sb;
X 	int i, size;
X 
-	if (!inode)
-		return 0;
-
X 	sb = inode->i_sb;
X 
X 	size = 2048 >> sb->s_blocksize_bits;
diff -u --recursive --new-file v2.2.9/linux/fs/adfs/namei.c linux/fs/adfs/namei.c
--- v2.2.9/linux/fs/adfs/namei.c	Tue May 11 13:10:30 1999
+++ linux/fs/adfs/namei.c	Thu May 13 23:25:58 1999
@@ -46,9 +46,6 @@
X 	unsigned long parent_object_id, dir_object_id;
X 	int buffers, pos;
X 
-	if (!S_ISDIR(dir->i_mode))
-		return 0;
-
X 	sb = dir->i_sb;
X 
X 	if (adfs_inode_validate (dir)) {
@@ -56,9 +53,6 @@
X 			    "invalid inode number: %lu", dir->i_ino);
X 		return 0;
X 	}
-
-	if (namelen > ADFS_NAME_LEN)
-		return 0;
X 
X 	if (!(buffers = adfs_dir_read (dir, bh))) {
X 		adfs_error (sb, "adfs_find_entry", "unable to read directory");
diff -u --recursive --new-file v2.2.9/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.2.9/linux/fs/autofs/dir.c	Wed Apr 28 11:37:30 1999
+++ linux/fs/autofs/dir.c	Thu May 13 23:25:58 1999
@@ -16,8 +16,6 @@
X 			       void *dirent, filldir_t filldir)
X {
X 	struct inode *inode=filp->f_dentry->d_inode;
-	if (!inode || !S_ISDIR(inode->i_mode))
-		return -ENOTDIR;
X 
X 	switch((unsigned long) filp->f_pos)
X 	{
diff -u --recursive --new-file v2.2.9/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.2.9/linux/fs/autofs/root.c	Tue May 11 13:10:30 1999
+++ linux/fs/autofs/root.c	Thu May 13 23:25:58 1999
@@ -72,9 +72,6 @@
X 	struct inode * inode = filp->f_dentry->d_inode;
X 	off_t onr, nr;
X 
-	if (!inode || !S_ISDIR(inode->i_mode))
-		return -ENOTDIR;
-
X 	sbi = autofs_sbi(inode->i_sb);
X 	dirhash = &sbi->dirhash;
X 	nr = filp->f_pos;
diff -u --recursive --new-file v2.2.9/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.2.9/linux/fs/binfmt_elf.c	Tue May 11 13:10:30 1999
+++ linux/fs/binfmt_elf.c	Sun Jun 13 10:50:04 1999
@@ -449,6 +449,8 @@
X 
X 	retval = -ENOMEM;
X 	size = elf_ex.e_phentsize * elf_ex.e_phnum;
+	if (size > 65536)
+		goto out;
X 	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
X 	if (!elf_phdata)
X 		goto out;
diff -u --recursive --new-file v2.2.9/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.2.9/linux/fs/block_dev.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/block_dev.c	Fri May 28 09:20:36 1999
@@ -273,6 +273,8 @@
X 			if (++bhe == &buflist[NBUF])
X 				bhe = buflist;
X 		} while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
+		if (bhe == bhb && !blocks)
+			break;
X 	} while (left > 0);
X 
X /* Release the read-ahead blocks */
diff -u --recursive --new-file v2.2.9/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.2.9/linux/fs/coda/inode.c	Tue Mar 23 14:35:48 1999
+++ linux/fs/coda/inode.c	Mon Jun  7 16:27:06 1999
@@ -145,7 +145,7 @@
X         sb->s_dev = 0;
X 	coda_cache_clear_all(sb);
X 	sb_info = coda_sbp(sb);
-	sb_info->sbi_vcomm->vc_inuse = 0;
+/*	sb_info->sbi_vcomm->vc_inuse = 0; You can not do this: psdev_release would see usagecount == 0 and would refuse to decrease MOD_USE_COUNT --pavel */ 
X 	coda_super_info.sbi_sb = NULL;
X 	printk("Coda: Bye bye.\n");
X 	memset(sb_info, 0, sizeof(* sb_info));
diff -u --recursive --new-file v2.2.9/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.2.9/linux/fs/coda/psdev.c	Fri Jan  8 22:36:13 1999
+++ linux/fs/coda/psdev.c	Wed Jun  2 11:29:28 1999
@@ -2,7 +2,7 @@
X  *      	An implementation of a loadable kernel mode driver providing
X  *		multiple kernel/user space bidirectional communications links.
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 15'
echo 'File patch-2.2.10 is continued in part 16'
echo 16 > _shar_seq_.tmp
#!/bin/sh
# this is part 13 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 13; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
@@ -5154,15 +5274,15 @@
X #if AIC7XXX_NOT_YET 
X     case TRACEPOINT:
X       {
-        printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no, channel,
-          target, lun);
+        printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no,
+               channel, target, lun);
X       }
X       break;
X 
X     case TRACEPOINT2:
X       {
-        printk(INFO_LEAD "Tracepoint #2 reached.\n", p->host_no, channel,
-          target, lun);
+        printk(INFO_LEAD "Tracepoint #2 reached.\n", p->host_no,
+               channel, target, lun);
X       }
X       break;
X 
@@ -5237,7 +5357,7 @@
X       case MSG_EXT_SDTR:
X       {
X         unsigned int period, offset;
-        unsigned char maxsync, saved_offset;
+        unsigned char maxsync, saved_offset, options;
X         struct aic7xxx_syncrate *syncrate;
X         
X         if (p->msg_buf[1] != MSG_EXT_SDTR_LEN)
@@ -5253,7 +5373,13 @@
X 
X         period = p->msg_buf[3];
X         saved_offset = offset = p->msg_buf[4];
+        options = 0;
X 
+        /*
+         * Even if we are an Ultra3 card, don't allow Ultra3 sync rates when
+         * using the SDTR messages.  We need the PPR messages to enable the
+         * higher speeds that include things like Dual Edge clocking.
+         */
X         if (p->features & AHC_ULTRA2)
X         {
X           if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
@@ -5283,7 +5409,9 @@
X         if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
X              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) )
X         {
-          if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+          if (!(p->dev_flags[tindex] & DEVICE_SCANNED) &&
+              !(p->needsdtr_copy & target_mask) &&
+               (p->transinfo[tindex].user_offset) )
X           {
X             /*
X              * Not only is the device starting this up, but it also hasn't
@@ -5295,38 +5423,49 @@
X              */
X             p->transinfo[tindex].goal_period =
X               p->transinfo[tindex].user_period;
-            p->transinfo[tindex].goal_offset =
-              p->transinfo[tindex].user_offset;
+            if(p->features & AHC_ULTRA2)
+            {
+              p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+            }
+ else if (p->transinfo[tindex].cur_width)
+            {
+              p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+            }
+            else
+            {
+              p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+            }
X             p->needsdtr_copy |= target_mask;
X           }
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Received pre-emptive SDTR message from "
+                   "target.\n", p->host_no, CTL_OF_SCB(scb));
+          }
X           if ( !p->transinfo[tindex].goal_offset )
X             period = 255;
X           if ( p->transinfo[tindex].goal_period > period )
X             period = p->transinfo[tindex].goal_period;
X         }
X   
-        syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
+        syncrate = aic7xxx_find_syncrate(p, &period, maxsync, &options);
X         aic7xxx_validate_offset(p, syncrate, &offset,
X                                 target_scsirate & WIDEXFER);
X         aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                             offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+                             offset, options, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
X 
X         /*
-         * Did we drop to async?  If so, are we sending a reply?  If we are,
+         * Did we drop to async?  Or are we sending a reply?  If we are,
X          * then we have to make sure that the reply value reflects the proper
X          * settings so we need to set the goal values according to what
X          * we need to send.
X          */
-        if ( (offset == 0) || (offset != saved_offset) ||
+        if ( (offset != saved_offset) ||
X              ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
X               (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) )
X         {
-          aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                               offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
-          if ( offset == 0 )
-          {
-            p->needsdtr_copy &= ~target_mask;
-          }
+          aic7xxx_set_syncrate(p, syncrate, target, channel, period, offset,
+                               options, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
X         }
X         
X         /*
@@ -5334,15 +5473,13 @@
X          * go async, then send an SDTR back to the target
X          */
X         p->needsdtr &= ~target_mask;
-        p->sdtr_pending &= ~target_mask;
-        if ( ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) ==
-              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) &&
-             (offset == saved_offset) )
-        {
-          scb->flags &= ~SCB_MSGOUT_BITS;
-        }
- else
+        p->dtr_pending &= ~target_mask;
+        if ( ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) ||
+             (offset != saved_offset) )
X         {
+          reply = TRUE;
+          p->dtr_pending |= target_mask;
X           scb->flags &= ~SCB_MSGOUT_BITS;
X           scb->flags |= SCB_MSGOUT_SDTR;
X           aic_outb(p, HOST_MSG, MSG_OUT);
@@ -5376,12 +5513,11 @@
X             {
X               reject = TRUE;
X               if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
-                   ((p->dev_flags[tindex] & DEVICE_PRINT_WDTR) ||
+                   ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
X                     (aic7xxx_verbose > 0xffff)) )
X               {
X                 printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n",
X                   p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width));
-                p->dev_flags[tindex] &= ~DEVICE_PRINT_WDTR;
X               }
X             } /* We fall through on purpose */
X             case MSG_EXT_WDTR_BUS_8_BIT:
@@ -5395,15 +5531,11 @@
X               break;
X             }
X           }
-          scb->flags &= ~SCB_MSGOUT_BITS;
-          p->wdtr_pending &= ~target_mask;
+          p->dtr_pending &= ~target_mask;
X           p->needwdtr &= ~target_mask;
X         }
X         else
X         {
-          scb->flags &= ~SCB_MSGOUT_BITS;
-          scb->flags |= SCB_MSGOUT_WDTR;
-          reply = TRUE;
X           if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
X           {
X             /* 
@@ -5413,13 +5545,33 @@
X              */
X             p->transinfo[tindex].goal_period =
X               p->transinfo[tindex].user_period;
-            p->transinfo[tindex].goal_offset =
-              p->transinfo[tindex].user_offset;
+            if(p->transinfo[tindex].user_offset)
+            {
+              if(p->features & AHC_ULTRA2)
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+              }
+              else if( p->transinfo[tindex].user_width &&
+                       (bus_width == MSG_EXT_WDTR_BUS_16_BIT) &&
+                       p->features & AHC_WIDE )
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+              }
+              else
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+              }
+            }
X             p->transinfo[tindex].goal_width =
X               p->transinfo[tindex].user_width;
X             p->needwdtr_copy |= target_mask;
X             p->needsdtr_copy |= target_mask;
X           }
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Received pre-emptive WDTR message from "
+                   "target.\n", p->host_no, CTL_OF_SCB(scb));
+          }
X           switch(bus_width)
X           {
X             default:
@@ -5441,8 +5593,11 @@
X               break;
X             }
X           }
+          reply = TRUE;
+          scb->flags &= ~SCB_MSGOUT_BITS;
+ scb->flags |= SCB_MSGOUT_WDTR;
X           p->needwdtr &= ~target_mask;
-          p->wdtr_pending &= ~target_mask;
+          p->dtr_pending |= target_mask;
X           aic_outb(p, HOST_MSG, MSG_OUT);
X           aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
X         }
@@ -5456,24 +5611,211 @@
X          * supports SDTR at all.  Therefore, we check needsdtr_copy instead
X          * of needstr.
X          */
-        aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0,
+        aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
X                              AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
-        if ( (p->needsdtr_copy & target_mask) &&
-            !(p->sdtr_pending & target_mask))
+        p->needsdtr |= (p->needsdtr_copy & target_mask);
+        done = TRUE;
+        break;
+      }
+      case MSG_EXT_PPR:
+      {
+        unsigned char bus_width, trans_options, new_trans_options;
+        unsigned int period, offset;
+        unsigned char maxsync, saved_offset;
+        struct aic7xxx_syncrate *syncrate;
+        
+        if (p->msg_buf[1] != MSG_EXT_PPR_LEN)
+        {
+          reject = TRUE;
+          break;
+        }
+
+        /*
+         * If we aren't on one of the new Ultra3 cards, then reject any PPR
+         * message since we can't support any option field other than 0
+         */
+        if( !(p->features & AHC_ULTRA3) )
+        {
+          reject = TRUE;
+          break;
+        }
+
+        if (p->msg_len < (MSG_EXT_PPR_LEN + 2))
+        {
+          break;
+        }
+
+        period = p->msg_buf[3];
+        offset = saved_offset = p->msg_buf[5];
+        bus_width = p->msg_buf[6];
+        trans_options = new_trans_options = p->msg_buf[7] & 0xf;
+
+        if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+        {
+          printk(INFO_LEAD "Parsing PPR message (%d/%d/%d/%d)\n",
+                 p->host_no, CTL_OF_SCB(scb), period, offset, bus_width,
+                 trans_options);
+        }
+
+        if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
+            !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
X         {
-          p->needsdtr |= target_mask;
-          if ( !reject && !reply )
+          if(p->features & AHC_ULTRA3)
+          {
+            maxsync = AHC_SYNCRATE_ULTRA3;
+          }
+          else
X           {
-            scb->flags &= ~SCB_MSGOUT_WDTR;
-            if (p->transinfo[tindex].goal_period)
+            maxsync = AHC_SYNCRATE_ULTRA2;
+          }
+        }
+        else
+        {
+          maxsync = AHC_SYNCRATE_ULTRA;
+        }
+        /*
+         * We might have a device that is starting negotiation with us
+         * before we can start up negotiation with it....be prepared to
+         * have a device ask for a higher speed then we want to give it
+         * in that case
+         */
+        if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
+             (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR) )
+        {
+          reply = TRUE;
+          scb->flags &= ~SCB_MSGOUT_BITS;
+          scb->flags |= SCB_MSGOUT_PPR;
+          if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+          {
+            /*
+             * Not only is the device starting this up, but it also hasn't
+             * been scanned yet, so this would likely be our TUR or our
+             * INQUIRY command at scan time, so we need to use the
+             * settings from the SEEPROM if they existed.  Of course, even
+             * if we didn't find a SEEPROM, we stuffed default values into
+             * the user settings anyway, so use those in all cases.
+             */
+            p->transinfo[tindex].goal_period =
+              p->transinfo[tindex].user_period;
+            if(p->transinfo[tindex].user_offset)
X             {
-              p->sdtr_pending |= target_mask;
-              scb->flags |= SCB_MSGOUT_SDTR;
-              aic_outb(p, HOST_MSG, MSG_OUT);
-              aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+ if(p->features & AHC_ULTRA2)
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+              }
+              else if( p->transinfo[tindex].user_width &&
+                       (bus_width == MSG_EXT_WDTR_BUS_16_BIT) &&
+                       p->features & AHC_WIDE )
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+              }
+              else
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+              }
+            }
+            p->transinfo[tindex].goal_width =
+ p->transinfo[tindex].user_width;
+            p->transinfo[tindex].goal_options =
+              p->transinfo[tindex].user_options;
+            p->needppr_copy |= target_mask;
+          }
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Received pre-emptive PPR message from "
+                   "target.\n", p->host_no, CTL_OF_SCB(scb));
+          }
+          if ( !p->transinfo[tindex].goal_offset )
+            period = 255;
+          if ( p->transinfo[tindex].goal_period > period )
+            period = p->transinfo[tindex].goal_period;
+          if ( p->transinfo[tindex].goal_options == 0 )
+            new_trans_options = 0;
+          switch(bus_width)
+          {
+            default:
+            {
+              if ( (p->features & AHC_WIDE) &&
+                   (p->transinfo[tindex].goal_width ==
+                    MSG_EXT_WDTR_BUS_16_BIT) )
+              {
+                bus_width = MSG_EXT_WDTR_BUS_16_BIT;
+                break;
+              }
+            } /* Fall through if we aren't a wide card */
+            case MSG_EXT_WDTR_BUS_8_BIT:
+            {
+              p->needwdtr_copy &= ~target_mask;
+              bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+              aic7xxx_set_width(p, target, channel, lun, bus_width,
+                                AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+              break;
+            }
+          }
+        }
+        else
+        {
+          switch(bus_width)
+          {
+            default:
+            {
+              reply = TRUE;
+              if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+                   ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
+                    (aic7xxx_verbose > 0xffff)) )
+              {
+                printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n",
+                  p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width));
+              }
+            } /* We fall through on purpose */
+            case MSG_EXT_WDTR_BUS_8_BIT:
+            {
+              /*
+               * According to the spec, if we aren't wide, we also can't be
+               * Dual Edge so clear the options byte
+               */
+              new_trans_options = 0;
+              bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+              break;
+            }
+            case MSG_EXT_WDTR_BUS_16_BIT:
+            {
+              break;
X             }
X           }
X         }
+
+        aic7xxx_set_width(p, target, channel, lun, bus_width,
+                          AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+        syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
+                                         &new_trans_options);
+        aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
+        aic7xxx_set_syncrate(p, syncrate, target, channel, period,
+                             offset, new_trans_options,
+                             AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+
+        if( (offset != saved_offset) ||
+            (trans_options != new_trans_options) ||
+            ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
+             (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) )
+        {
+          aic7xxx_set_width(p, target, channel, lun, bus_width,
+                            AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+          aic7xxx_set_syncrate(p, syncrate, target, channel, period,
+                               offset, new_trans_options,
+                               AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+          reply = TRUE;
+        }
+        p->dtr_pending &= ~target_mask;
+        p->needppr &= ~target_mask;
+ if(reply)
+        {
+          p->dtr_pending |= target_mask;
+ scb->flags &= ~SCB_MSGOUT_BITS;
+          scb->flags |= SCB_MSGOUT_PPR;
+          aic_outb(p, HOST_MSG, MSG_OUT);
+          aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+        }
X         done = TRUE;
X         break;
X       }
@@ -5485,7 +5827,7 @@
X     } /* end of switch(p->msg_type) */
X   } /* end of if (!reject && (p->msg_len > 2)) */
X 
-  if (reject)
+  if (!reply && reject)
X   {
X     aic_outb(p, MSG_MESSAGE_REJECT, MSG_OUT);
X     aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
@@ -5657,12 +5999,14 @@
X     if (aic7xxx_verbose & VERBOSE_RESET)
X       printk(WARN_LEAD "Someone else reset the channel!!\n",
X            p->host_no, channel, -1, -1);
+    if (aic7xxx_panic_on_abort)
+      aic7xxx_panic_abort(p, NULL);
X     /*
X      * Go through and abort all commands for the channel, but do not
X      * reset the channel again.
X      */
X     aic7xxx_reset_channel(p, channel, /* Initiate Reset */ FALSE);
-    aic7xxx_run_done_queue(p, FALSE);
+    aic7xxx_run_done_queue(p, TRUE);
X     scb = NULL;
X   }
X   else if ( ((status & BUSFREE) != 0) && ((status & SELTO) == 0) )
@@ -5698,7 +6042,7 @@
X             CTL_OF_SCB(scb), scb->hscb->tag);
X         aic7xxx_reset_device(p, target, channel, ALL_LUNS,
X                 (message == MSG_ABORT) ? SCB_LIST_NULL : scb->hscb->tag );
-        aic7xxx_run_done_queue(p, FALSE);
+        aic7xxx_run_done_queue(p, TRUE);
X         scb = NULL;
X         printerror = 0;
X       }
@@ -5709,6 +6053,22 @@
X         printerror = 0;
X       }
X     }
+    if ( (scb != NULL) &&
+         (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)]) )
+    {
+      /*
+       * This might be a SCSI-3 device that is dropping the bus due to
+       * errors and signalling that we should reduce the transfer speed.
+       * All we have to do is complete this command (since it's a negotiation
+       * command already) and the checksum routine should flag an error and
+       * reduce the speed setting and renegotiate.  We call the reset routing
+       * just to clean out the hardware from this scb.
+       */
+      printerror = 0;
+      aic7xxx_reset_device(p, target, channel, ALL_LUNS, scb->hscb->tag);
+      aic7xxx_run_done_queue(p, TRUE);
+      scb = NULL;
+    }
X     if (printerror != 0)
X     {
X       if (scb != NULL)
@@ -5724,7 +6084,12 @@
X           tag = SCB_LIST_NULL;
X         }
X         aic7xxx_reset_device(p, target, channel, ALL_LUNS, tag);
-        aic7xxx_run_done_queue(p, FALSE);
+        aic7xxx_run_done_queue(p, TRUE);
+      }
+      else
+      {
+        aic7xxx_reset_device(p, target, channel, ALL_LUNS, SCB_LIST_NULL);
+        aic7xxx_run_done_queue(p, TRUE);
X       }
X       printk(INFO_LEAD "Unexpected busfree, LASTPHASE = 0x%x, "
X              "SEQADDR = 0x%x\n", p->host_no, channel, target, -1, lastphase,
@@ -5829,12 +6194,26 @@
X         cmd->result = 0;
X         scb = NULL;
X       }
+      if (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)])
+      {
+        /*
+         * Turn off the needsdtr, needwdtr, and needppr bits since this device
+         * doesn't seem to exist.
+         */
+        p->needppr &= ~(0x01 << TARGET_INDEX(scb->cmd));
+        p->needppr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
+        p->needsdtr &= ~(0x01 << TARGET_INDEX(scb->cmd));
+        p->needsdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
+        p->needwdtr &= ~(0x01 << TARGET_INDEX(scb->cmd));
+        p->needwdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
+      }
X     }
X     /*
X      * Restarting the sequencer will stop the selection and make sure devices
X      * are allowed to reselect in.
X      */
X     aic_outb(p, 0, SCSISEQ);
+    aic_outb(p, CLRSELINGO, CLRSINT0);
X     aic_outb(p, aic_inb(p, SIMODE1) & ~(ENREQINIT|ENBUSFREE), SIMODE1);
X     p->flags &= ~AHC_HANDLING_REQINITS;
X     aic_outb(p, CLRSELTIMEO | CLRBUSFREE, CLRSINT1);
@@ -5868,6 +6247,8 @@
X     Scsi_Cmnd *cmd;
X     unsigned char mesg_out = MSG_NOOP;
X     unsigned char lastphase = aic_inb(p, LASTPHASE);
+    unsigned char sstat2 = aic_inb(p, SSTAT2);
+    unsigned char tindex = TARGET_INDEX(scb->cmd);
X 
X     cmd = scb->cmd;
X     switch (lastphase)
@@ -5898,12 +6279,81 @@
X         break;
X     }
X 
-    /*
-     * A parity error has occurred during a data
-     * transfer phase. Flag it and continue.
-     */
-    printk(WARN_LEAD "Parity error during %s phase.\n",
-           p->host_no, CTL_OF_SCB(scb), phase);
+    /*
+     * A parity error has occurred during a data
+     * transfer phase. Flag it and continue.
+     */
+    if( (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) && (lastphase == P_DATAIN) )
+    {
+      printk(WARN_LEAD "CRC error during %s phase.\n",
+             p->host_no, CTL_OF_SCB(scb), phase);
+      if(sstat2 & CRCVALERR)
+      {
+        printk(WARN_LEAD "  CRC error in intermediate CRC packet.\n",
+               p->host_no, CTL_OF_SCB(scb));
+      }
+      if(sstat2 & CRCENDERR)
+      {
+        printk(WARN_LEAD "  CRC error in ending CRC packet.\n",
+               p->host_no, CTL_OF_SCB(scb));
+      }
+      if(sstat2 & CRCREQERR)
+      {
+        printk(WARN_LEAD "  Target incorrectly requested a CRC packet.\n",
+               p->host_no, CTL_OF_SCB(scb));
+      }
+      if(sstat2 & DUAL_EDGE_ERROR)
+      {
+        printk(WARN_LEAD "  Dual Edge transmission error.\n",
+               p->host_no, CTL_OF_SCB(scb));
+      }
+    }
+    else
+    {
+      printk(WARN_LEAD "Parity error during %s phase.\n",
+             p->host_no, CTL_OF_SCB(scb), phase);
+    }
+
+    if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
+    {
+      struct aic7xxx_syncrate *syncrate;
+      unsigned int period = p->transinfo[tindex].cur_period;
+      unsigned char options = p->transinfo[tindex].cur_options;
+      /*
+       * oops, we had a failure, lower the transfer rate and try again.  It's
+       * worth noting here that it might be wise to also check for typical
+       * wide setting on narrow cable type problems and try disabling wide
+       * instead of slowing down if those exist.  That's hard to do with simple
+       * checksums though.
+       */
+      if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
+      {
+        syncrate++;
+        if( (syncrate->rate[0] != NULL) &&
+            (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
+        {
+          p->transinfo[tindex].goal_period = syncrate->period;
+          if( !(syncrate->sxfr_ultra2 & 0x40) )
+          {
+            p->transinfo[tindex].goal_options = 0;
+          }
+        }
+        else
+        {
+          p->transinfo[tindex].goal_offset = 0;
+          p->transinfo[tindex].goal_period = 0;
+          p->transinfo[tindex].goal_options = 0;
+        }
+        p->needppr |= (p->needppr_copy & (1<<tindex));
+        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+      }
+      p->dev_flags[tindex] &= ~DEVICE_PARITY_ERROR;
+    }
+    else
+    {
+      p->dev_flags[tindex] |= DEVICE_PARITY_ERROR;
+    }
X 
X     /*
X      * We've set the hardware to assert ATN if we get a parity
@@ -6072,13 +6522,6 @@
X       printk("HSCB %d bad, SCB_NEXT points to self.\n", i);
X       bogus = TRUE;
X     }
-    temp = aic_inb(p, SCB_PREV);
-    if ((temp != SCB_LIST_NULL) &&
-        (temp >= p->scb_data->maxhscbs))
-    {
-      printk("HSCB %d bad, SCB_PREV invalid(%d).\n", i, temp);
-      bogus = TRUE;
-    }
X     if (scb_status[i] == 0)
X       lost++;
X     if (lost > 1)
@@ -6163,7 +6606,7 @@
X     unsigned char scb_index;
X 
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
-    if(aic7xxx_verbose > 0xffff)
+    if( (p->isr_count < 16) && (aic7xxx_verbose > 0xffff) )
X       printk(INFO_LEAD "Command Complete Int.\n", p->host_no, -1, -1, -1);
X #endif
X     
@@ -6368,7 +6811,7 @@
X  *   Determines the queue depth for a given device.  There are two ways
X  *   a queue depth can be obtained for a tagged queueing device.  One
X  *   way is the default queue depth which is determined by whether
- *   AIC7XXX_CMDS_PER_LUN is defined.  If it is defined, then it is used
+ *   AIC7XXX_CMDS_PER_DEVICE is defined.  If it is defined, then it is used
X  *   as the default queue depth.  Otherwise, we use either 4 or 8 as the
X  *   default queue depth (dependent on the number of hardware SCBs).
X  *   The other way we determine queue depth is through the use of the
@@ -6396,7 +6839,7 @@
X   {
X     int tag_enabled = TRUE;
X 
-    default_depth = AIC7XXX_CMDS_PER_LUN;
+    default_depth = AIC7XXX_CMDS_PER_DEVICE;
X  
X     if (!(p->discenable & target_mask))
X     {
@@ -6958,7 +7401,7 @@
X   }
X   printk("\n");
X #endif
-  if (checksum != scarray[len - 1])
+  if ( (checksum != scarray[len - 1]) || (checksum == 0) )
X   {
X     return (0);
X   }
@@ -7371,7 +7814,6 @@
X       aic_outb(p, i, SCBPTR);
X       aic_outb(p, 0, SCB_CONTROL);   /* Clear the control byte. */
X       aic_outb(p, i + 1, SCB_NEXT);  /* Set the next pointer. */
-      aic_outb(p, i - 1, SCB_PREV);  /* Set the prev pointer. */
X       aic_outb(p, SCB_LIST_NULL, SCB_TAG);  /* Make the tag invalid. */
X       aic_outb(p, SCB_LIST_NULL, SCB_BUSYTARGETS);  /* no busy untagged */
X       aic_outb(p, SCB_LIST_NULL, SCB_BUSYTARGETS+1);/* targets active yet */
@@ -7840,6 +8282,11 @@
X    */
X   aic7xxx_loadseq(p);
X 
+  /*
+   * Make sure the AUTOFLUSHDIS bit is *not* set in the SBLKCTL register
+   */
+  aic_outb(p, aic_inb(p, SBLKCTL) & ~AUTOFLUSHDIS, SBLKCTL);
+
X   if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 )
X   {
X     aic_outb(p, ENABLE, BCTL);  /* Enable the boards BUS drivers. */
@@ -8035,6 +8482,7 @@
X     {
X       p->transinfo[i].goal_period = 0;
X       p->transinfo[i].goal_offset = 0;
+      p->transinfo[i].goal_options = 0;
X       p->transinfo[i].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
X     }
X     DRIVER_LOCK_INIT
@@ -8090,10 +8538,14 @@
X    */
X   for (i = 0; i < MAX_TARGETS; i++)
X   {
-    if(p->dev_wdtr_cmnd[i])
-      kfree(p->dev_wdtr_cmnd[i]);
-    if(p->dev_sdtr_cmnd[i])
-      kfree(p->dev_sdtr_cmnd[i]);
+    if(p->dev_dtr_cmnd[i])
+    {
+      if(p->dev_dtr_cmnd[i]->request_buffer)
+      {
+        kfree(p->dev_dtr_cmnd[i]->request_buffer);
+      }
+      kfree(p->dev_dtr_cmnd[i]);
+    }
X   }
X 
X }
@@ -8184,14 +8636,16 @@
X     {
X       printk("aic7xxx: Using leftover BIOS values.\n");
X     }
-    if ( *sxfrctl1 & STPWEN )
+    if ( ((p->chip & ~AHC_CHIPID_MASK) == AHC_PCI) && (*sxfrctl1 & STPWEN) )
X     {
X       p->flags |= AHC_TERM_ENB_SE_LOW | AHC_TERM_ENB_SE_HIGH;
X       sc->adapter_control &= ~CFAUTOTERM;
X       sc->adapter_control |= CFSTERM | CFWSTERM | CFLVDSTERM;
X     }
X     if (aic7xxx_extended)
-      p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
+      p->flags |= (AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
+    else
+      p->flags &= ~(AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
X   }
X   else
X   {
@@ -8256,8 +8710,7 @@
X    * Limit to 16 targets just in case.  The 2842 for one is known to
X    * blow the max_targets setting, future cards might also.
X    */
-  max_targets = MIN(sc->max_targets & CFMAXTARG,
-                   ((p->features & (AHC_TWIN | AHC_WIDE)) ? 16 : 8));
+  max_targets = ((p->features & (AHC_TWIN | AHC_WIDE)) ? 16 : 8);
X 
X   if (have_seeprom)
X   {
@@ -8279,7 +8732,7 @@
X     mask = (0x01 << i);
X     if (!have_seeprom)
X     {
-      if(aic_inb(p, SCSISEQ) != 0)
+      if (aic_inb(p, SCSISEQ) != 0)
X       {
X         /*
X          * OK...the BIOS set things up and left behind the settings we need.
@@ -8323,7 +8776,9 @@
X         sc->device_flags[i] = CFDISC;
X         if (p->features & AHC_WIDE)
X           sc->device_flags[i] |= CFWIDEB;
-        if (p->features & AHC_ULTRA2)
+        if (p->features & AHC_ULTRA3)
+          sc->device_flags[i] |= 2;
+        else if (p->features & AHC_ULTRA2)
X           sc->device_flags[i] |= 3;
X         else if (p->features & AHC_ULTRA)
X           sc->device_flags[i] |= CFSYNCHISULTRA;
@@ -8339,20 +8794,30 @@
X     }
X     if (p->flags & AHC_NEWEEPROM_FMT)
X     {
-      if (sc->device_flags[i] & CFSYNCHISULTRA)
-      {
-        p->ultraenb |= mask;
-      }
-      else if (sc->device_flags[i] & CFNEWULTRAFORMAT)
+      if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) &&
+          !(p->features & AHC_ULTRA2) )
X       {
-        if ( ((sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03) &&
-             !(p->features & AHC_ULTRA2) )
+        /*
+         * I know of two different Ultra BIOSes that do this differently.
+         * One on the Gigabyte 6BXU mb that wants flags[i] & CFXFER to
+         * be == to 0x03 and SYNCISULTRA to be true to mean 40MByte/s
+         * while on the IBM Netfinity 5000 they want the same thing
+         * to be something else, while flags[i] & CFXFER == 0x03 and
+         * SYNCISULTRA false should be 40MByte/s.  So, we set both to
+         * 40MByte/s and the lower speeds be damned.  People will have
+         * to select around the conversely mapped lower speeds in order
+         * to select lower speeds on these boards.
+         */
+        if ((sc->device_flags[i] & (CFXFER)) == 0x03)
X         {
X           sc->device_flags[i] &= ~CFXFER;
X           sc->device_flags[i] |= CFSYNCHISULTRA;
-          p->ultraenb |= mask;
X         }
X       }
+      if (sc->device_flags[i] & CFSYNCHISULTRA)
+      {
+        p->ultraenb |= mask;
+      }
X     }
X     else if (sc->adapter_control & CFULTRAEN)
X     {
@@ -8364,18 +8829,54 @@
X       p->ultraenb &= ~mask;
X       p->transinfo[i].user_offset = 0;
X       p->transinfo[i].user_period = 0;
+      p->transinfo[i].user_options = 0;
X       p->transinfo[i].cur_offset = 0;
X       p->transinfo[i].cur_period = 0;
+      p->transinfo[i].cur_options = 0;
X       p->needsdtr_copy &= ~mask;
X     }
X     else
X     {
-      if (p->features & AHC_ULTRA2)
+      if (p->features & AHC_ULTRA3)
+      {
+        p->transinfo[i].user_offset = MAX_OFFSET_ULTRA2;
+        p->transinfo[i].cur_offset = aic_inb(p, TARG_OFFSET + i);
+        if( (sc->device_flags[i] & CFXFER) < 0x03 )
+        {
+          scsirate = (sc->device_flags[i] & CFXFER);
+          p->transinfo[i].user_options = MSG_EXT_PPR_OPTION_DT_CRC;
+          if( (aic_inb(p, TARG_SCSIRATE + i) & CFXFER) < 0x03 )
+          {
+            p->transinfo[i].cur_options = 
+              ((aic_inb(p, TARG_SCSIRATE + i) & 0x40) ?
+                 MSG_EXT_PPR_OPTION_DT_CRC : MSG_EXT_PPR_OPTION_DT_UNITS);
+          }
+          else
+          {
+            p->transinfo[i].cur_options = 0;
+          }
+        }
+        else
+        {
+          scsirate = (sc->device_flags[i] & CFXFER) |
+                     ((p->ultraenb & mask) ? 0x18 : 0x10);
+          p->transinfo[i].user_options = 0;
+          p->transinfo[i].cur_options = 0;
+        }
+        p->transinfo[i].user_period = aic7xxx_find_period(p, scsirate,
+                                       AHC_SYNCRATE_ULTRA3);
+        p->transinfo[i].cur_period = aic7xxx_find_period(p,
+                                       aic_inb(p, TARG_SCSIRATE + i),
+                                       AHC_SYNCRATE_ULTRA3);
+      }
+      else if (p->features & AHC_ULTRA2)
X       {
X         p->transinfo[i].user_offset = MAX_OFFSET_ULTRA2;
X         p->transinfo[i].cur_offset = aic_inb(p, TARG_OFFSET + i);
X         scsirate = (sc->device_flags[i] & CFXFER) |
X                    ((p->ultraenb & mask) ? 0x18 : 0x10);
+        p->transinfo[i].user_options = 0;
+        p->transinfo[i].cur_options = 0;
X         p->transinfo[i].user_period = aic7xxx_find_period(p, scsirate,
X                                        AHC_SYNCRATE_ULTRA2);
X         p->transinfo[i].cur_period = aic7xxx_find_period(p,
@@ -8385,10 +8886,9 @@
X       else
X       {
X         scsirate = (sc->device_flags[i] & CFXFER) << 4;
-        if (sc->device_flags[i] & CFWIDEB)
-          p->transinfo[i].user_offset = MAX_OFFSET_16BIT;
-        else
-          p->transinfo[i].user_offset = MAX_OFFSET_8BIT;
+        p->transinfo[i].user_options = 0;
+        p->transinfo[i].cur_options = 0;
+        p->transinfo[i].user_offset = MAX_OFFSET_8BIT;
X         if (p->features & AHC_ULTRA)
X         {
X           short ultraenb;
@@ -8427,9 +8927,10 @@
X   }
X   aic_outb(p, ~(p->discenable & 0xFF), DISC_DSB);
X   aic_outb(p, ~((p->discenable >> 8) & 0xFF), DISC_DSB + 1);
+  p->needppr = p->needppr_copy = p->needdv = 0;
X   p->needwdtr = p->needwdtr_copy;
X   p->needsdtr = p->needsdtr_copy;
-  p->wdtr_pending = p->sdtr_pending = 0;
+  p->dtr_pending = 0;
X 
X   /*
X    * We set the p->ultraenb from the SEEPROM to begin with, but now we make
@@ -8453,6 +8954,7 @@
X     {
X       case AHC_AIC7895:
X       case AHC_AIC7896:
+      case AHC_AIC7899:
X         if (p->adapter_control & CFBPRIMARY)
X           p->flags |= AHC_CHANNEL_B_PRIMARY;
X       default:
@@ -8783,6 +9285,14 @@
X       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7855, AHC_AIC7850,
X        AHC_PAGESCBS, AHC_AIC7850_FE,                         6,
X        32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7821, AHC_AIC7860,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7860_FE,                                       7,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_3860, AHC_AIC7860,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7860_FE,                                       7,
+       32, C46 },
X       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X        AHC_AIC7860_FE,                                       7,
@@ -8825,6 +9335,18 @@
X       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7884, AHC_AIC7880,
X        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
X        32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7885, AHC_AIC7880,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7886, AHC_AIC7880,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
+       32, C46 },
X       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
X        AHC_AIC7895_FE,                                      19,
@@ -8833,30 +9355,66 @@
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X        AHC_AIC7890_FE,                                      20,
X        32, C46 },
-      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_78902, AHC_AIC7890,
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X        AHC_AIC7890_FE,                                      20,
X        32, C46 },
-      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X        AHC_AIC7890_FE,                                      21,
X        32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7890_FE,                                      22,
+       32, C46 },
X       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      22,
+       AHC_AIC7896_FE,                                      23,
X        32, C56_66 },
X       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      23,
+       AHC_AIC7896_FE,                                      24,
X        32, C56_66 },
X       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      24,
+       AHC_AIC7896_FE,                                      25,
X        32, C56_66 },
X       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
X        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7860_FE,                                      25,
+       AHC_AIC7860_FE,                                      26,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7892_FE,                                      27,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7892_FE,                                      27,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7892_FE,                                      27,
+       32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7892_FE,                                      27,
X        32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+       AHC_AIC7899_FE,                                      28,
+       32, C56_66 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+       AHC_AIC7899_FE,                                      28,
+       32, C56_66 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+       AHC_AIC7899_FE,                                      28,
+       32, C56_66 },
+      {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+       AHC_AIC7899_FE,                                      28,
+       32, C56_66 },
X     };
X 
X     unsigned short command;
@@ -8926,11 +9484,11 @@
X           }
X #ifdef AIC7XXX_STRICT_PCI_SETUP
X           command |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
-            PCI_COMMAND_INVALIDATE | PCI_COMMAND_MASTER |
-            PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+            PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #else
X           command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #endif
+          command &= ~PCI_COMMAND_INVALIDATE;
X           if (aic7xxx_pci_parity == 0)
X             command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
X           pci_write_config_word(pdev, PCI_COMMAND, command);
@@ -8940,15 +9498,7 @@
X           {
X             printk("aic7xxx: Initial DEVCONFIG value was 0x%x\n", devconfig);
X           }
-          devconfig |= 0x80000000;
-          if ((aic7xxx_pci_parity == 0) || (aic7xxx_pci_parity == -1))
-          {
-            devconfig &= ~(0x00000008);
-          }
-          else
-          {
-            devconfig |= 0x00000008;
-          }
+          devconfig |= 0x80000040;
X           pci_write_config_dword(pdev, DEVCONFIG, devconfig);
X #endif /* AIC7XXX_STRICT_PCI_SETUP */
X #else  /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
@@ -8976,11 +9526,11 @@
X           }
X #ifdef AIC7XXX_STRICT_PCI_SETUP
X           command |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
-            PCI_COMMAND_INVALIDATE | PCI_COMMAND_MASTER |
-            PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+            PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #else
X           command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #endif
+          command &= ~PCI_COMMAND_INVALIDATE;
X           if (aic7xxx_pci_parity == 0)
X             command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
X           pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, command);
@@ -8990,15 +9540,7 @@
X           {
X             printk("aic7xxx: Initial DEVCONFIG value was 0x%x\n", devconfig);
X           }
-          devconfig |= 0x80000000;
-          if ((aic7xxx_pci_parity == 0) || (aic7xxx_pci_parity == -1))
-          {
-            devconfig &= ~(0x00000008);
-          }
-          else
-          {
-            devconfig |= 0x00000008;
-          }
+          devconfig |= 0x80000040;
X           pcibios_write_config_dword(pci_bus, pci_devfn, DEVCONFIG, devconfig);
X #endif /* AIC7XXX_STRICT_PCI_SETUP */
X #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
@@ -9137,6 +9679,7 @@
X 
X             case AHC_AIC7895: /* 7895 */
X             case AHC_AIC7896: /* 7896/7 */
+            case AHC_AIC7899: /* 7899 */
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X               if (PCI_FUNC(temp_p->pdev->devfn) != 0)
X               {
@@ -9185,43 +9728,38 @@
X            */
X           switch (temp_p->chip & AHC_CHIPID_MASK)
X           {
-            case AHC_AIC7890:
-            case AHC_AIC7896:
+            case AHC_AIC7892:
+            case AHC_AIC7899:
X               aic_outb(temp_p, 0, SCAMCTL);
X               /*
-               * We used to set DPARCKEN in this register, but after talking
-               * to a tech from Adaptec, I found out they don't use that
-               * particular bit in their own register settings, and when you
-               * combine that with the fact that I determined that we were
-               * seeing Data-Path Parity Errors on things we shouldn't see
-               * them on, I think there is a bug in the silicon and the way
-               * to work around it is to disable this particular check.  Also
-               * This bug only showed up on certain commands, so it seems to
-               * be pattern related or some such.  The commands we would
-               * typically send as a linux TEST_UNIT_READY or INQUIRY command
-               * could cause it to be triggered, while regular commands that
-               * actually made reasonable use of the SG array capabilities
-               * seemed not to cause the problem.
+               * Switch to the alt mode of the chip...
+               */
+              aic_outb(temp_p, aic_inb(temp_p, SFUNCT) | ALT_MODE, SFUNCT);
+              /*
+               * Set our options...the last two items set our CRC after x byte
+	       * count in target mode...
X                */
+              aic_outb(temp_p, AUTO_MSGOUT_DE | DIS_MSGIN_DUALEDGE, OPTIONMODE);
+	      aic_outb(temp_p, 0x00, 0x0b);
+	      aic_outb(temp_p, 0x10, 0x0a);
X               /*
-              aic_outb(temp_p, aic_inb(temp_p, DSCOMMAND0) |
-                               CACHETHEN | DPARCKEN | MPARCKEN |
-                               USCBSIZE32 | CIOPARCKEN,
-                               DSCOMMAND0);
+               * switch back to normal mode...
X                */
+              aic_outb(temp_p, aic_inb(temp_p, SFUNCT) & ~ALT_MODE, SFUNCT);
+              aic_outb(temp_p, CRCVALCHKEN | CRCENDCHKEN | CRCREQCHKEN |
+			       TARGCRCENDEN | TARGCRCCNTEN,
+                       CRCCONTROL1);
+              aic_outb(temp_p, ((aic_inb(temp_p, DSCOMMAND0) | USCBSIZE32 |
+                                 MPARCKEN | CIOPARCKEN | CACHETHEN) & 
+                               ~DPARCKEN), DSCOMMAND0);
+              aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+              break;
+            case AHC_AIC7890:
+            case AHC_AIC7896:
+              aic_outb(temp_p, 0, SCAMCTL);
X               aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
X                                 CACHETHEN | MPARCKEN | USCBSIZE32 |
X                                 CIOPARCKEN) & ~DPARCKEN, DSCOMMAND0);
-              /* FALLTHROUGH */
-            default:
-              /*
-               * We attempt to read a SEEPROM on *everything*.  If we fail,
-               * then we fail, but this covers things like 2910c cards that
-               * now have SEEPROMs with their 7856 chipset that we would
-               * otherwise ignore.  They still don't have a BIOS, but they
-               * have a SEEPROM that the SCSISelect utility on the Adaptec
-               * diskettes can configure.
-               */
X               aic7xxx_load_seeprom(temp_p, &sxfrctl1);
X               break;
X             case AHC_AIC7850:
@@ -9233,14 +9771,13 @@
X               aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
X                                 CACHETHEN | MPARCKEN) & ~DPARCKEN,
X                        DSCOMMAND0);
+              /* FALLTHROUGH */
+            default:
X               aic7xxx_load_seeprom(temp_p, &sxfrctl1);
X               break;
X             case AHC_AIC7880:
X               /*
-               * Only set the DSCOMMAND0 register if this is a Rev B.
-               * chipset.  For those, we also enable Ultra mode by
-               * force due to brain-damage on the part of some BIOSes
-               * We overload the devconfig variable here since we can.
+               * Check the rev of the chipset before we change DSCOMMAND0
X                */
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X               pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
@@ -9272,6 +9809,7 @@
X           {
X             case AHC_AIC7895:
X             case AHC_AIC7896:
+            case AHC_AIC7899:
X               current_p = list_p;
X               while(current_p != NULL)
X               {
@@ -9315,6 +9853,7 @@
X               break;
X             case AHC_AIC7895:
X             case AHC_AIC7896:
+            case AHC_AIC7899:
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X               pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
X #else
@@ -9364,7 +9903,7 @@
X            */
X           if (temp_p->features & AHC_ULTRA2)
X           {
-            aic_outb(temp_p, RD_DFTHRSH_75 | WR_DFTHRSH_75, DFF_THRSH);
+            aic_outb(temp_p, RD_DFTHRSH_MAX | WR_DFTHRSH_MAX, DFF_THRSH);
X           }
X           else
X           {
@@ -9512,7 +10051,7 @@
X               }
X             }
X             /*
-             * Are we dealing with a 7985 where we need to sort the
+             * Are we dealing with a 7895/6/7/9 where we need to sort the
X              * channels as well, if so, the bios_address values should
X              * be the same
X              */
@@ -9603,7 +10142,54 @@
X   return (found);
X }
X 
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
+static void aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p,
+                                           Scsi_Cmnd *old_cmd, int tindex);
+
+/*+F*************************************************************************
+ * Function:
+ * aic7xxx_allocate_negotiation_command
+ *
+ * Description:
+ *   allocate the actual command struct and fill in the gaps...
+ *-F*************************************************************************/
+static Scsi_Cmnd *
+aic7xxx_allocate_negotiation_command(struct aic7xxx_host *p,
+                                     Scsi_Cmnd *old_cmd, int tindex)
+{
+  Scsi_Cmnd *cmd;
+  char *buffer;
+
+  if (!(p->dev_dtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+  {
+    return(NULL);
+  }
+  if (!(buffer = kmalloc(256, GFP_ATOMIC)))
+  {
+    kfree(p->dev_dtr_cmnd[tindex]);
+    p->dev_dtr_cmnd[tindex] = NULL;
+    return(NULL);
+  }
+  cmd = p->dev_dtr_cmnd[tindex];
+  memset(cmd, 0, sizeof(Scsi_Cmnd));
+  memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
+  memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
+  memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
+  cmd->lun = 0;
+  cmd->request_bufflen = 255;
+  cmd->request_buffer = buffer;
+  cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
+  cmd->bufflen = 0;
+  cmd->buffer = NULL;
+  cmd->underflow = 0;
+  cmd->cmd_len = 6;
+  cmd->cmnd[0] = cmd->data_cmnd[0] = INQUIRY;
+  cmd->cmnd[1] = cmd->data_cmnd[1] = 0;
+  cmd->cmnd[2] = cmd->data_cmnd[2] = 0;
+  cmd->cmnd[3] = cmd->data_cmnd[3] = 0;
+  cmd->cmnd[4] = cmd->data_cmnd[4] = 255; /* match what scsi.c does here */
+  cmd->cmnd[5] = cmd->data_cmnd[5] = 0;
+  return(cmd);
+}
X 
X /*+F*************************************************************************
X  * Function:
@@ -9616,6 +10202,117 @@
X static void
X aic7xxx_negotiation_complete(Scsi_Cmnd *cmd)
X {
+  unsigned int checksum;
+  int i;
+  int *ibuffer;
+  struct aic7xxx_host *p = (struct aic7xxx_host *)cmd->host->hostdata;
+  int tindex = TARGET_INDEX(cmd);
+  struct aic7xxx_syncrate *syncrate;
+
+  /*
+   * perform our minimalistic domain validation
+   */
+  if(p->dev_flags[tindex] & DEVICE_SCANNED)
+  {
+    ibuffer = (int *)cmd->request_buffer;
+    checksum = 0;
+    for(i = 0; i < (cmd->request_bufflen >> 2); i++)
+    {
+      checksum += ibuffer[i];
+    }
+    if( (checksum != p->dev_checksum[tindex]) &&
+        (p->transinfo[tindex].cur_offset != 0) )
+    {
+      unsigned int period = p->transinfo[tindex].cur_period;
+      unsigned char options = p->transinfo[tindex].cur_options;
+
+      if (p->needdv & (1<<tindex))
+      {
+        /*
+         * oops, we had a failure, lower the transfer rate and try again.  It's
+         * worth noting here that it might be wise to also check for typical
+         * wide setting on narrow cable type problems and try disabling wide
+         * instead of slowing down if those exist.  That's hard to do with simple
+         * checksums though.
+         */
+        if(aic7xxx_verbose & VERBOSE_NEGOTIATION) 
+        {
+          printk(INFO_LEAD "reducing SCSI transfer speed due to Domain "
+                 "validation failure.\n", p->host_no, CTL_OF_CMD(cmd));
+        }
+        if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
+        {
+          syncrate++;
+          if( (syncrate->rate[0] != NULL) &&
+              (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
+          {
+            p->transinfo[tindex].goal_period = syncrate->period;
+            if( !(syncrate->sxfr_ultra2 & 0x40) )
+            {
+              p->transinfo[tindex].goal_options = 0;
+            }
+          }
+          else
+          {
+            p->transinfo[tindex].goal_offset = 0;
+            p->transinfo[tindex].goal_period = 0;
+            p->transinfo[tindex].goal_options = 0;
+          }
+          p->needppr |= (p->needppr_copy & (1<<tindex));
+          p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+          p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+        }
+        p->needdv &= ~(1<<tindex);
+      }
+      else
+      {
+        if(aic7xxx_verbose & VERBOSE_NEGOTIATION) 
+        {
+          printk(INFO_LEAD "Performing Domain validation.\n",
+                 p->host_no, CTL_OF_CMD(cmd));
+        }
+        /*
+         * Update the checksum in case the INQUIRY data has changed, maybe
+         * in relation to a change in the mode pages, or whatever.
+         */
+        p->dev_checksum[tindex] = checksum;
+        /*
+         * Signal that we are trying out the domain validation
+         */
+        p->needdv |= (1<<tindex);
+        /*
+         * Signal that we need to re-negotiate things, this also gets us our
+         * INQUIRY command to re-checksum off of.
+         */
+        p->needppr |= (p->needppr_copy & (1<<tindex));
+        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+      }
+    } 
+    else
+    {
+      if( (aic7xxx_verbose & VERBOSE_NEGOTIATION) &&
+          (p->needdv & (1<<tindex)) )
+      {
+        printk(INFO_LEAD "Successfully completed Domain validation.\n",
+               p->host_no, CTL_OF_CMD(cmd));
+      }
+      /*
+       * We successfully did our checksum, so don't leave the needdv flag set
+       * in case we might have set it last time through.
+       */
+      p->needdv &= ~(1<<tindex);
+    }
+  }
+
+  p->dtr_pending &= ~(0x01 << tindex);
+  /*
+   * This looks recursive in the extreme, but if this was a WDTR negotiation
+   * and we didn't follow up with SDTR yet, then this will get it started.
+   * For all other cases, this should work out to be a no-op, unless we are
+   * doing domain validation and happen to need a new negotiation command.
+   */
+  aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
X   return;
X }
X 
@@ -9632,81 +10329,63 @@
X   int tindex)
X {
X 
-  if ( (p->needwdtr & (1<<tindex)) && !(p->wdtr_pending & (1<<tindex)) )
+  if ( !(p->dtr_pending & (1<<tindex)) &&
+       ( (p->needppr & (1<<tindex)) ||
+         (p->needwdtr & (1<<tindex)) ||
+         (p->needsdtr & (1<<tindex)) ) )
X   {
-    if(p->dev_wdtr_cmnd[tindex] == NULL)
+    if ( (p->dev_dtr_cmnd[tindex] == NULL) &&
+         (aic7xxx_allocate_negotiation_command(p, old_cmd, tindex) == NULL) )
X     {
-      Scsi_Cmnd *cmd;
-
-      if (!(p->dev_wdtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
-      {
-        return;
-      }
-      cmd = p->dev_wdtr_cmnd[tindex];
-      memset(cmd, 0, sizeof(Scsi_Cmnd));
-      memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
-      memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
-      memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
-      cmd->lun = 0;
-      cmd->request_bufflen = 0;
-      cmd->request_buffer = NULL;
-      cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
-      cmd->bufflen = 0;
-      cmd->buffer = NULL;
-      cmd->underflow = 0;
-      cmd->cmd_len = 6;
+      return;
X     }
X     /*
-     * Before sending this thing out, we also amke the cmd->next pointer
+     * Before sending this thing out, we also make the cmd->next pointer
X      * point to the real command so we can stuff any possible SENSE data
-     * intp the real command instead of this fake command.  This has to be
+     * into the real command instead of this fake command.  This has to be
X      * done each time the command is built, not just the first time, hence
X      * it's outside of the above if()...
X      */
-    p->dev_wdtr_cmnd[tindex]->next = old_cmd;
-    aic7xxx_queue(p->dev_wdtr_cmnd[tindex], 
-                  aic7xxx_negotiation_complete);
-  }
-  else if ( (p->needsdtr & (1<<tindex)) && !(p->sdtr_pending & (1<<tindex)) &&
-            !(p->wdtr_pending & (1<<tindex)) )
-  {
-    if(p->dev_sdtr_cmnd[tindex] == NULL)
+    p->dev_dtr_cmnd[tindex]->next = old_cmd;
+    /*
+     * Clear the buffer so checksums come out right....
+     */
+    memset(p->dev_dtr_cmnd[tindex]->request_buffer, 0,
+           p->dev_dtr_cmnd[tindex]->request_bufflen);
+    /*
+     * Remove any commands for this particular device that might be on the
+     * waiting_scbs queue or qinfifo so that this command goes out first.
+     * This is vital for our implementation of domain validation.
+     */
+    pause_sequencer(p);
+    aic7xxx_search_qinfifo(p, old_cmd->target, old_cmd->channel, ALL_LUNS,
+                SCB_LIST_NULL, 0, TRUE, &p->delayed_scbs[tindex]);
+    unpause_sequencer(p, FALSE);
X     {
-      Scsi_Cmnd *cmd;
+      struct aic7xxx_scb *scb, *next;
X 
-      if (!(p->dev_sdtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+      scb = p->waiting_scbs.head;
+      while(scb != NULL)
X       {
-        return;
+        if( aic7xxx_match_scb(p, scb, old_cmd->target, old_cmd->channel,
+                              ALL_LUNS, SCB_LIST_NULL) )
+        {
+          next = scb->q_next;
+          scbq_remove(&p->waiting_scbs, scb);
+          scbq_insert_tail(&p->delayed_scbs[tindex], scb);
+          scb = next;
+        }
+        else
+        {
+          scb = scb->q_next;
+        }
X       }
-      cmd = p->dev_sdtr_cmnd[tindex];
-      memset(cmd, 0, sizeof(Scsi_Cmnd));
-      memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
-      memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
-      memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
-      cmd->lun = 0;
-      cmd->request_bufflen = 0;
-      cmd->request_buffer = NULL;
-      cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
-      cmd->bufflen = 0;
-      cmd->buffer = NULL;
-      cmd->underflow = 0;
-      cmd->cmd_len = 6;
X     }
-    /*
-     * Before sending this thing out, we also amke the cmd->next pointer
-     * point to the real command so we can stuff any possible SENSE data
-     * intp the real command instead of this fake command.  This has to be
-     * done each time the command is built, not just the first time, hence
-     * it's outside of the above if()...
-     */
-    p->dev_sdtr_cmnd[tindex]->next = old_cmd;
-    aic7xxx_queue(p->dev_sdtr_cmnd[tindex], 
+    aic7xxx_queue(p->dev_dtr_cmnd[tindex], 
X                   aic7xxx_negotiation_complete);
X   }
X }
X 
-#endif
-
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
X /*+F*************************************************************************
X  * Function:
@@ -9744,8 +10423,9 @@
X {
X   unsigned short mask;
X   struct aic7xxx_hwscb *hscb;
+  unsigned char tindex = TARGET_INDEX(cmd);
X 
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 13'
echo 'File patch-2.2.10 is continued in part 14'
echo 14 > _shar_seq_.tmp
#!/bin/sh
# this is part 04 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 04; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
X 	break;
+     case X86_VENDOR_CENTAUR:
+        get_mtrr = centaur_get_mcr;
+        set_mtrr_up = centaur_set_mcr_up;
+        break;
X     }
X }   /*  End Function mtrr_setup  */
X 
@@ -1611,6 +1694,9 @@
X       case X86_VENDOR_CYRIX:
X 	cyrix_arr_init ();
X 	break;
+      case X86_VENDOR_CENTAUR:
+        centaur_mcr_init ();
+        break;
X     }
X }   /*  End Function mtrr_init_boot_cpu  */
X 
@@ -1675,6 +1761,9 @@
X       case X86_VENDOR_CYRIX:
X 	cyrix_arr_init ();
X 	break;
+      case X86_VENDOR_CENTAUR:
+        centaur_mcr_init ();
+        break;
X     }
X #  endif  /*  !__SMP__  */
X 
diff -u --recursive --new-file v2.2.9/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.9/linux/arch/i386/kernel/setup.c	Tue May 11 13:10:27 1999
+++ linux/arch/i386/kernel/setup.c	Tue Jun  8 10:43:21 1999
@@ -9,6 +9,11 @@
X  *  Force Cyrix 6x86(MX) and M II processors to report MTRR capability
X  *  and fix against Cyrix "coma bug" by
X  *      Zoltan Boszormenyi <zbo...@mol.hu> February 1999.
+ * 
+ *  Force Centaur C6 processors to report MTRR capability.
+ *      Bart Hartgers <ba...@etpmod.phys.tue.nl>, May 199.
+ *
+ *  Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
X  */
X 
X /*
@@ -685,7 +690,7 @@
X 	    NULL, NULL, NULL, NULL }},
X 	{ X86_VENDOR_INTEL,	6,
X 	  { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", 
-	    NULL, "Pentium II (Deschutes)", "Celeron (Mendocino)", NULL,
+            NULL, "Pentium II (Deschutes)", "Mobile Pentium II", NULL,
X 	    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
X 	{ X86_VENDOR_AMD,	4,
X 	  { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB",
@@ -791,13 +796,19 @@
X 			if (c->x86_model <= 16)
X 				p = cpu_models[i].model_names[c->x86_model];
X 
-			/* Names for the Pentium II processors */
+			/* Names for the Pentium II Celeron processors 
+                           detectable only by also checking the cache size */
X 			if ((cpu_models[i].vendor == X86_VENDOR_INTEL)
-			    && (cpu_models[i].x86 == 6) 
-			    && (c->x86_model == 5)
-			    && (c->x86_cache_size == 0)) {
-				p = "Celeron (Covington)";
-			}
+			    && (cpu_models[i].x86 == 6)){ 
+				if(c->x86_model == 6 && c->x86_cache_size == 128) {
+                            		p = "Celeron (Mendocino)"; 
+                          	}
+			  	else { 
+                            	if (c->x86_model == 5 && c->x86_cache_size == 0) {
+				  	p = "Celeron (Covington)";
+			    	}
+                        }
+                    }
X 		}
X 			
X 	}
@@ -861,6 +872,8 @@
X 		/* lv|=(1<<6);	- may help too if the board can cope */
X 		printk("now 0x%X", lv);
X 		wrmsr(0x107, lv, hv);
+		/* Emulate MTRRs using Centaur's MCR. */
+		c->x86_capability |= X86_FEATURE_MTRR;	   	
X 	}
X 	printk("\n");
X }
diff -u --recursive --new-file v2.2.9/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.2.9/linux/arch/i386/kernel/signal.c	Wed Dec 16 10:32:54 1998
+++ linux/arch/i386/kernel/signal.c	Mon Jun  7 16:14:20 1999
@@ -698,6 +698,7 @@
X 			default:
X 				lock_kernel();
X 				sigaddset(¤t->signal, signr);
+				recalc_sigpending(current);
X 				current->flags |= PF_SIGNALED;
X 				do_exit(exit_code);
X 				/* NOTREACHED */
diff -u --recursive --new-file v2.2.9/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.9/linux/arch/i386/kernel/smp.c	Tue May 11 13:10:27 1999
+++ linux/arch/i386/kernel/smp.c	Wed Jun  2 11:29:27 1999
@@ -2,7 +2,7 @@
X  *	Intel MP v1.1/v1.4 specification support routines for multi-pentium
X  *	hosts.
X  *
- *	(c) 1995 Alan Cox, CymruNET Ltd  <al...@cymru.net>
+ *	(c) 1995 Alan Cox, Building #3 <al...@redhat.com>
X  *	(c) 1998 Ingo Molnar
X  *
X  *	Supported by Caldera http://www.caldera.com.
diff -u --recursive --new-file v2.2.9/linux/arch/i386/lib/checksum.S linux/arch/i386/lib/checksum.S
--- v2.2.9/linux/arch/i386/lib/checksum.S	Tue Jan 19 11:32:51 1999
+++ linux/arch/i386/lib/checksum.S	Tue Jun  1 14:05:46 1999
@@ -369,7 +369,7 @@
X 
X #define ROUND1(x) \
X 	SRC(movl x(%esi), %ebx	)	;	\
-	addl %ebx, %eax\n		;	\
+	addl %ebx, %eax			;	\
X 	DST(movl %ebx, x(%edi)	)	; 
X 
X #define ROUND(x) \
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.2.9/linux/arch/ppc/Makefile	Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/Makefile	Fri Jun  4 13:30:47 1999
@@ -29,6 +29,10 @@
X CFLAGS := $(CFLAGS) -mcpu=860
X endif
X 
+ifdef CONFIG_PPC64
+CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-Wa,-mppc64
+#CFLAGS := $(CFLAGS) -Wa,-mppc64 -mpowerpc64
+endif
X 
X HEAD := arch/ppc/kernel/head.o
X 
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.2.9/linux/arch/ppc/boot/Makefile	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/boot/Makefile	Fri Jun  4 13:30:47 1999
@@ -26,9 +26,15 @@
X ISZ = 0
X 
X ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.prep.smp
+TFTPIMAGE=/tftpboot/zImage.prep.smp$(MSIZE)
X else
-TFTPIMAGE=/tftpboot/zImage.prep
+TFTPIMAGE=/tftpboot/zImage.prep$(MSIZE)
+endif
+
+ifeq ($(CONFIG_PPC64),y)
+MSIZE=.64
+else
+MSIZE=
X endif
X 
X ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.2.9/linux/arch/ppc/boot/misc.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/boot/misc.c	Fri Jun  4 13:30:47 1999
@@ -1,7 +1,7 @@
X /*
X  * misc.c
X  *
- * $Id: misc.c,v 1.64 1999/04/30 05:52:46 cort Exp $
+ * $Id: misc.c,v 1.64.2.2 1999/05/29 19:09:29 cort Exp $
X  * 
X  * Adapted for PowerPC by Gary Thomas
X  *
@@ -363,7 +363,7 @@
X 			if (board_type == 0xe0) {	
X 				base_mod = inb(0x803);
X 				/* if a MVME2300/2400 or a Sitka then no keyboard */
-				if((base_mod == 0x9) || (base_mod == 0xF9) ||
+				if((base_mod == 0xFA) || (base_mod == 0xF9) ||
X 				   (base_mod == 0xE1)) {
X 					keyb_present = 0;	/* no keyboard */
X 				}
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.2.9/linux/arch/ppc/chrpboot/Makefile	Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/chrpboot/Makefile	Fri Jun  4 13:30:47 1999
@@ -17,21 +17,27 @@
X 	$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
X 
X CFLAGS	= -O -fno-builtin -DSTDC_HEADERS -I$(TOPDIR)/include
-LD_ARGS = -T ../vmlinux.lds -Ttext 0x00800000
+LD_ARGS = -Ttext 0x00400000
X OBJCOPY = $(CROSS_COMPILE)objcopy
X 
X OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o # initrd.o
X LIBS = $(TOPDIR)/lib/lib.a
X 
+ifeq ($(CONFIG_PPC64),y)
+MSIZE=.64
+else
+MSIZE=
+endif
+
X ifeq ($(CONFIG_ALL_PPC),y)
X # yes, we want to build chrp stuff
X CONFIG_CHRP = y
X endif
X 
X ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.chrp.smp
+TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE)
X else
-TFTPIMAGE=/tftpboot/zImage.chrp
+TFTPIMAGE=/tftpboot/zImage.chrp$(MSIZE)
X endif
X 
X all:	$(TOPDIR)/zImage
@@ -59,9 +65,10 @@
X initrd.o: ramdisk.image.gz piggyback
X 	./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o
X 
-zImage: $(OBJS) no_initrd.o
+zImage: $(OBJS) no_initrd.o mknote
X 	$(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
-	objcopy zImage zImage
+	./mknote > note
+	$(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
X 
X zImage.initrd: $(OBJS) initrd.o
X 	$(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
@@ -86,8 +93,7 @@
X 
X 
X clean:
-	rm -f piggyback
-	rm -f $(OBJS) zImage
+	rm -f piggyback note mknote $(OBJS) zImage
X 
X fastdep:
X 	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- v2.2.9/linux/arch/ppc/chrpboot/main.c	Mon Oct  5 13:13:36 1998
+++ linux/arch/ppc/chrpboot/main.c	Fri Jun  4 13:30:47 1999
@@ -17,9 +17,9 @@
X #define get_32be(x)	(*(unsigned *)(x))
X 
X #define RAM_START	0x00000000
-#define RAM_END		0x00800000	/* only 8M mapped with BATs */
+#define RAM_END		(8<<20)
X 
-#define RAM_FREE	0x00540000	/* after image of chrpboot */
+#define RAM_FREE	(6<<20)		/* after image of chrpboot */
X #define PROG_START	0x00010000
X 
X char *avail_ram;
@@ -38,16 +38,16 @@
X     void *dst;
X     unsigned char *im;
X     unsigned initrd_start, initrd_size;
+    extern char _start;
X     
-    printf("chrpboot starting\n\r");
-    /* setup_bats(); */
+    printf("chrpboot starting: loaded at 0x%x\n\r", &_start);
X 
X     if (initrd_len) {
X 	initrd_size = initrd_len;
X 	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
X 	a1 = initrd_start;
X 	a2 = initrd_size;
-	printf("initial ramdisk at %x (%u bytes)\n\r", initrd_start,
+	printf("initial ramdisk at 0x%x (%u bytes)\n\r", initrd_start,
X 	       initrd_size);
X 	memcpy((char *)initrd_start, initrd_data, initrd_size);
X 	end_avail = (char *)initrd_start;
@@ -58,25 +58,19 @@
X     dst = (void *) PROG_START;
X 
X     if (im[0] == 0x1f && im[1] == 0x8b) {
-	void *cp = (void *) RAM_FREE;
-	avail_ram = (void *) (RAM_FREE + ((len + 7) & -8));
-	memcpy(cp, im, len);
-	printf("gunzipping... ");
-	gunzip(dst, 0x400000, cp, &len);
-	printf("done\n\r");
-
+	avail_ram = (char *)RAM_FREE;
+	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
+	gunzip(dst, 0x400000, im, &len);
+	printf("done %u bytes\n\r", len);
X     } else {
X 	memmove(dst, im, len);
X     }
X 
X     flush_cache(dst, len);
-
-    sa = PROG_START+12;
+    
+    sa = *(unsigned long *)PROG_START+PROG_START;
X     printf("start address = 0x%x\n\r", sa);
X 
-#if 0
-    pause();
-#endif
X     (*(void (*)())sa)(a1, a2, prom, 0, 0);
X 
X     printf("returned?\n\r");
@@ -150,7 +144,7 @@
X     s.avail_out = dstlen;
X     r = inflate(&s, Z_FINISH);
X     if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d\n\r", r);
+	printf("inflate returned %d msg: %s\n\r", r, s.msg);
X 	exit();
X     }
X     *lenp = s.next_out - (unsigned char *) dst;
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.2.9/linux/arch/ppc/coffboot/Makefile	Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/coffboot/Makefile	Fri Jun  4 13:30:47 1999
@@ -23,10 +23,16 @@
X CONFIG_PMAC = y
X endif
X 
+ifeq ($(CONFIG_PPC64),y)
+MSIZE=.64
+else
+MSIZE=
+endif
+
X ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.pmac.smp
+TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE)
X else
-TFTPIMAGE=/tftpboot/zImage.pmac
+TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE)
X endif
X 
X ifeq ($(CONFIG_PMAC),y)
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/coffboot/zlib.c linux/arch/ppc/coffboot/zlib.c
--- v2.2.9/linux/arch/ppc/coffboot/zlib.c	Mon Oct  5 13:13:36 1998
+++ linux/arch/ppc/coffboot/zlib.c	Fri Jun  4 13:30:47 1999
@@ -11,7 +11,7 @@
X  * - added Z_PACKET_FLUSH (see zlib.h for details)
X  * - added inflateIncomp
X  *
- * $Id: zlib.c,v 1.2 1998/09/03 17:40:53 cort Exp $
+ * $Id: zlib.c,v 1.2.2.1 1999/05/29 19:09:42 cort Exp $
X  */
X 
X /*+++++*/
@@ -649,6 +649,11 @@
X /*   load local pointers */
X #define LOAD {LOADIN LOADOUT}
X 
+/*
+ * The IBM 150 firmware munges the data right after _etext[].  This
+ * protects it. -- Cort
+ */
+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
X /* And'ing with mask[n] masks the lower n bits */
X local uInt inflate_mask[] = {
X     0x0000,
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.2.9/linux/arch/ppc/common_defconfig	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/common_defconfig	Fri Jun  4 13:30:47 1999
@@ -7,6 +7,7 @@
X #
X CONFIG_PPC=y
X CONFIG_6xx=y
+# CONFIG_PPC64 is not set
X # CONFIG_8xx is not set
X # CONFIG_PMAC is not set
X # CONFIG_PREP is not set
@@ -15,13 +16,14 @@
X # CONFIG_APUS is not set
X # CONFIG_MBX is not set
X # CONFIG_SMP is not set
+CONFIG_6xx=y
X 
X #
X # General setup
X #
X CONFIG_EXPERIMENTAL=y
X CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
X CONFIG_KMOD=y
X CONFIG_PCI=y
X # CONFIG_PCI_QUIRKS is not set
@@ -32,7 +34,7 @@
X # CONFIG_BSD_PROCESS_ACCT is not set
X CONFIG_BINFMT_ELF=y
X CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=m
+# CONFIG_BINFMT_MISC is not set
X # CONFIG_BINFMT_JAVA is not set
X # CONFIG_PARPORT is not set
X CONFIG_VGA_CONSOLE=y
@@ -58,7 +60,7 @@
X #
X # Block devices
X #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
X CONFIG_BLK_DEV_IDE=y
X 
X #
@@ -73,15 +75,17 @@
X # CONFIG_BLK_DEV_CMD640 is not set
X # CONFIG_BLK_DEV_RZ1000 is not set
X # CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_SL82C105=y
X CONFIG_BLK_DEV_IDE_PMAC=y
-# CONFIG_BLK_DEV_IDEDMA_PMAC is not set
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_PMAC_IDEDMA_AUTO=y
X # CONFIG_IDE_CHIPSETS is not set
X 
X #
X # Additional Block Devices
X #
-CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_LOOP is not set
X # CONFIG_BLK_DEV_NBD is not set
X # CONFIG_BLK_DEV_MD is not set
X CONFIG_BLK_DEV_RAM=y
@@ -110,7 +114,7 @@
X # CONFIG_NET_IPGRE is not set
X # CONFIG_IP_MROUTE is not set
X CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
+CONFIG_SYN_COOKIES=y
X 
X #
X # (it is safe to leave these untouched)
@@ -151,12 +155,12 @@
X CONFIG_CHR_DEV_ST=y
X CONFIG_BLK_DEV_SR=y
X CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SG is not set
X 
X #
X # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
X #
-CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_MULTI_LUN is not set
X CONFIG_SCSI_CONSTANTS=y
X # CONFIG_SCSI_LOGGING is not set
X 
@@ -191,13 +195,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_SYM53C8XX is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
X CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
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_NCR53C8XX_SYMBIOS_COMPAT is not set
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
@@ -301,27 +306,17 @@
X CONFIG_FB_CT65550=y
X # CONFIG_FB_S3TRIO is not set
X CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
+# CONFIG_FB_MATROX_MILLENIUM is not set
X CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_G100 is not set
X # CONFIG_FB_MATROX_MULTIHEAD is not set
X # CONFIG_FB_ATY is not set
X # CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
+# CONFIG_FBCON_ADVANCED is not set
X CONFIG_FBCON_CFB8=y
X CONFIG_FBCON_CFB16=y
X CONFIG_FBCON_CFB24=y
X CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA is not set
X # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
X CONFIG_FBCON_FONTS=y
X # CONFIG_FONT_8x8 is not set
@@ -355,7 +350,7 @@
X # CONFIG_PC110_PAD is not set
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
+CONFIG_NVRAM=y
X # CONFIG_RTC is not set
X 
X #
@@ -390,10 +385,10 @@
X # CONFIG_ADFS_FS is not set
X # CONFIG_AFFS_FS is not set
X CONFIG_HFS_FS=y
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
X # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
+CONFIG_VFAT_FS=y
X CONFIG_ISO9660_FS=y
X # CONFIG_JOLIET is not set
X # CONFIG_MINIX_FS is not set
@@ -470,7 +465,34 @@
X # CONFIG_SOUND_SONICVIBES is not set
X # CONFIG_SOUND_MSNDCLAS is not set
X # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+CONFIG_SOUND_CS4232=m
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
X 
X #
X # Kernel hacking
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.2.9/linux/arch/ppc/config.in	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/config.in	Fri Jun  4 13:30:47 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.92 1999/04/30 05:41:43 cort Exp $
+# $Id: config.in,v 1.92.2.1 1999/05/29 19:09:16 cort Exp $
X # For a description of the syntax of this configuration file,
X # see the Configure script.
X #
@@ -8,8 +8,9 @@
X comment 'Platform support'
X define_bool CONFIG_PPC y
X choice 'Processor type' \
-	"6xx/7xx	CONFIG_6xx \
-	 860/821	CONFIG_8xx" 6xx/7xx
+	"6xx/7xx		CONFIG_6xx \
+	 630/Power3(64-Bit) 	CONFIG_PPC64 \
+	 860/821		CONFIG_8xx" 6xx/7xx
X 
X choice 'Machine Type' \
X 	"PowerMac	CONFIG_PMAC \
@@ -22,6 +23,10 @@
X bool 'Symmetric multi-processing support' CONFIG_SMP
X if [ "$CONFIG_ALL_PPC" != "y" ];then
X   define_bool CONFIG_MACH_SPECIFIC y
+fi
+
+if [ "$CONFIG_PPC64" != "y" ];then
+  define_bool CONFIG_6xx y
X fi
X endmenu
X 
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.2.9/linux/arch/ppc/defconfig	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/defconfig	Fri Jun  4 13:30:47 1999
@@ -8,12 +8,13 @@
X CONFIG_PPC=y
X CONFIG_6xx=y
X # CONFIG_8xx is not set
-# CONFIG_PMAC is not set
+CONFIG_PMAC=y
X # CONFIG_PREP is not set
X # CONFIG_CHRP is not set
-CONFIG_ALL_PPC=y
+# CONFIG_ALL_PPC is not set
X # CONFIG_APUS is not set
X # CONFIG_MBX is not set
+CONFIG_MACH_SPECIFIC=y
X # CONFIG_SMP is not set
X 
X #
@@ -35,20 +36,20 @@
X CONFIG_BINFMT_MISC=m
X # CONFIG_BINFMT_JAVA is not set
X # CONFIG_PARPORT is not set
-CONFIG_VGA_CONSOLE=y
+# CONFIG_VGA_CONSOLE is not set
X CONFIG_FB=y
X CONFIG_FB_COMPAT_XPMAC=y
X CONFIG_PMAC_PBOOK=y
X CONFIG_MAC_KEYBOARD=y
X CONFIG_MAC_FLOPPY=y
X CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
X CONFIG_ADBMOUSE=y
+CONFIG_BLK_DEV_IDE_PMAC=y
X CONFIG_PROC_DEVICETREE=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
X # CONFIG_TOTALMP is not set
X CONFIG_BOOTX_TEXT=y
-# CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
X 
X #
X # Plug and Play support
@@ -75,13 +76,15 @@
X # CONFIG_BLK_DEV_IDEPCI is not set
X # CONFIG_BLK_DEV_SL82C105 is not set
X CONFIG_BLK_DEV_IDE_PMAC=y
-# CONFIG_BLK_DEV_IDEDMA_PMAC is not set
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_PMAC_IDEDMA_AUTO=y
X # CONFIG_IDE_CHIPSETS is not set
X 
X #
X # Additional Block Devices
X #
-CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_LOOP is not set
X # CONFIG_BLK_DEV_NBD is not set
X # CONFIG_BLK_DEV_MD is not set
X CONFIG_BLK_DEV_RAM=y
@@ -116,6 +119,7 @@
X # (it is safe to leave these untouched)
X #
X CONFIG_INET_RARP=y
+CONFIG_IP_NOSR=y
X CONFIG_SKB_LARGE=y
X # CONFIG_IPV6 is not set
X 
@@ -151,12 +155,12 @@
X CONFIG_CHR_DEV_ST=y
X CONFIG_BLK_DEV_SR=y
X CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SG is not set
X 
X #
X # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
X #
-CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_MULTI_LUN is not set
X CONFIG_SCSI_CONSTANTS=y
X # CONFIG_SCSI_LOGGING is not set
X 
@@ -184,28 +188,16 @@
X # CONFIG_SCSI_FUTURE_DOMAIN is not set
X # CONFIG_SCSI_GDTH is not set
X # CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_G_NCR5380_PORT is not set
-# CONFIG_SCSI_G_NCR5380_MEM is not set
X # CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
X # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
-# CONFIG_SCSI_SYM53C8XX is not set
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_NCR53C8XX is not set
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
X # CONFIG_SCSI_PCI2220I is not set
X # CONFIG_SCSI_PSI240I is not set
X # CONFIG_SCSI_QLOGIC_FAS is not set
X # CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
X # CONFIG_SCSI_SEAGATE is not set
X # CONFIG_SCSI_DC390T is not set
X # CONFIG_SCSI_T128 is not set
@@ -236,7 +228,7 @@
X # CONFIG_ACENIC is not set
X # CONFIG_NET_ISA is not set
X CONFIG_NET_EISA=y
-CONFIG_PCNET32=y
+# CONFIG_PCNET32 is not set
X # CONFIG_AC3200 is not set
X # CONFIG_APRICOT is not set
X # CONFIG_CS89x0 is not set
@@ -283,7 +275,7 @@
X # CONFIG_ISDN is not set
X 
X #
-# Old CD-ROM drivers (not SCSI, not IDE)
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
X #
X # CONFIG_CD_NO_IDESCSI is not set
X 
@@ -291,37 +283,22 @@
X # Console drivers
X #
X CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_PM2 is not set
X CONFIG_FB_OF=y
X CONFIG_FB_CONTROL=y
X CONFIG_FB_PLATINUM=y
X CONFIG_FB_VALKYRIE=y
-# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY=y
X CONFIG_FB_IMSTT=y
X CONFIG_FB_CT65550=y
X # CONFIG_FB_S3TRIO is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_ATY is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_ATY=y
X # CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
+# CONFIG_FBCON_ADVANCED is not set
X CONFIG_FBCON_CFB8=y
X CONFIG_FBCON_CFB16=y
X CONFIG_FBCON_CFB24=y
X CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA is not set
X # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
X CONFIG_FBCON_FONTS=y
X # CONFIG_FONT_8x8 is not set
@@ -337,25 +314,15 @@
X #
X CONFIG_VT=y
X CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
+# CONFIG_SERIAL is not set
X # CONFIG_SERIAL_EXTENDED is not set
X # CONFIG_SERIAL_NONSTANDARD is not set
X CONFIG_UNIX98_PTYS=y
X CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_MOUSE=y
-
-#
-# Mice
-#
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
+# CONFIG_MOUSE is not set
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
+CONFIG_NVRAM=y
X # CONFIG_RTC is not set
X 
X #
@@ -367,20 +334,11 @@
X # Joystick support
X #
X # CONFIG_JOYSTICK is not set
-# CONFIG_DTLK is not set
X 
X #
X # Ftape, the floppy tape device driver
X #
X # CONFIG_FTAPE is not set
-# CONFIG_FT_NORMAL_DEBUG is not set
-# CONFIG_FT_FULL_DEBUG is not set
-# CONFIG_FT_NO_TRACE is not set
-# CONFIG_FT_NO_TRACE_AT_ALL is not set
-# CONFIG_FT_STD_FDC is not set
-# CONFIG_FT_MACH2 is not set
-# CONFIG_FT_PROBE_FC10 is not set
-# CONFIG_FT_ALT_FDC is not set
X 
X #
X # Filesystems
@@ -471,10 +429,3 @@
X # CONFIG_SOUND_MSNDCLAS is not set
X # CONFIG_SOUND_MSNDPIN is not set
X # CONFIG_SOUND_OSS is not set
-
-#
-# Kernel hacking
-#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.2.9/linux/arch/ppc/kernel/Makefile	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/Makefile	Fri Jun  4 13:30:47 1999
@@ -65,7 +65,7 @@
X 	$(HOSTCC) -o find_name find_name.c
X 
X checks: checks.c
-	$(HOSTCC) -fno-builtin -I$(TOPDIR)/include -D__KERNEL__ -o checks checks.c
+	$(HOSTCC) ${CFLAGS} -D__KERNEL__ -o checks checks.c
X 	./checks
X 
X include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.2.9/linux/arch/ppc/kernel/chrp_pci.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/chrp_pci.c	Fri Jun  4 13:30:47 1999
@@ -166,6 +166,62 @@
X 	return PCIBIOS_SUCCESSFUL;
X }
X 
+
+int rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+				    unsigned char offset, unsigned char *val)
+{
+	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+	if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 1 ) != 0 )
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+				    unsigned char offset, unsigned short *val)
+{
+	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+	if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 2 ) != 0 )
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+				     unsigned char offset, unsigned int *val)
+{
+	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+	if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 4 ) != 0 )
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+				     unsigned char offset, unsigned char val)
+{
+	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+	if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 1, (ulong)val ) != 0 )
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+				     unsigned char offset, unsigned short val)
+{
+	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+	if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 2, (ulong)val ) != 0 )
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+				      unsigned char offset, unsigned int val)
+{
+	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+	if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 4, (ulong)val ) != 0 )
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return PCIBIOS_SUCCESSFUL;
+}
+
X     /*
X      *  Temporary fixes for PCI devices. These should be replaced by OF query
X      *  code -- Geert
@@ -255,6 +311,7 @@
X 
X decl_config_access_method(grackle);
X decl_config_access_method(indirect);
+decl_config_access_method(rtas);
X 
X void __init
X chrp_setup_pci_ptrs(void)
@@ -275,7 +332,7 @@
X 		{
X 			/* find out how many pythons */
X 			while ( (py = py->next) ) python_busnr++;
-                        set_config_access_method(python);
+			set_config_access_method(python);
X 			/*
X 			 * We base these values on the machine type but should
X 			 * try to read them from the python controller itself.
@@ -296,10 +353,22 @@
X                 }
X                 else
X                 {
-			pci_dram_offset = 0;
-			isa_mem_base = 0xf7000000;
-			isa_io_base = 0xf8000000;
-			set_config_access_method(gg2);
+			if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) )
+			{
+				pci_dram_offset = 0;
+				isa_mem_base = 0x80000000;
+				isa_io_base = 0xfe000000;
+				pci_config_address = (unsigned int *)0xfec00000;
+				pci_config_data = (unsigned char *)0xfee00000;
+				set_config_access_method(indirect);
+			}
+			else
+			{
+				pci_dram_offset = 0;
+				isa_mem_base = 0xf7000000;
+				isa_io_base = 0xf8000000;
+				set_config_access_method(gg2);
+			}
X                 }
X         }
X 	
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.2.9/linux/arch/ppc/kernel/chrp_setup.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Fri Jun  4 13:30:47 1999
@@ -32,6 +32,7 @@
X #include <linux/console.h>
X #include <linux/pci.h>
X #include <linux/openpic.h>
+#include <linux/version.h>
X 
X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -64,6 +65,7 @@
X 
X unsigned long chrp_get_rtc_time(void);
X int chrp_set_rtc_time(unsigned long nowtime);
+unsigned long rtas_event_scan_rate = 0, rtas_event_scan_ct = 0;
X void chrp_calibrate_decr(void);
X void chrp_time_init(void);
X 
@@ -179,6 +181,7 @@
X 	return len;
X }
X 
+#if 0
X /*
X      *  Fixes for the National Semiconductor PC78308VUL SuperI/O
X      *
@@ -228,12 +231,13 @@
X 	/* select logical device 1 (KBC/Mouse) */
X 	sio_fixup_irq("mouse", 1, 12, 2);
X }
-
+#endif
X 
X __initfunc(void
X 	   chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
X {
X 	extern char cmd_line[];
+	struct device_node *device;
X 
X 	/* init to some ~sane value until calibrate_delay() runs */
X 	loops_per_sec = 50000000;
@@ -273,80 +277,73 @@
X 			find_path_device("/"), "platform-open-pic", NULL);
X 		OpenPIC = ioremap((unsigned long)OpenPIC, sizeof(struct OpenPIC));
X 	}
-	
+
X 	/*
X 	 *  Fix the Super I/O configuration
X 	 */
-	sio_init();
+	/*sio_init();*/
X #ifdef CONFIG_DUMMY_CONSOLE
X 	conswitchp = &dummy_con;
X #endif
-	/* my starmax 6000 needs this but the longtrail shouldn't do it -- Cort */
-	if ( !strncmp("MOT", get_property(find_path_device("/"),
-					  "model", NULL),3) )
-		*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
-	/*
-	 * The f50 has a lot of IO space - we need to map some in that
-	 * isn't covered by the BAT mappings in MMU_init() -- Cort
+	*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+
+	/* Get the event scan rate for the rtas so we know how
+	 * often it expects a heartbeat. -- Cort
X 	 */
-	if ( !strncmp("F5", get_property(find_path_device("/"),
-					 "ibm,model-class", NULL),2) )
+	if ( rtas_data )
X 	{
-#if 0		
-		/*
-		 * This ugly hack allows us to force ioremap() to
-		 * create a 1-to-1 mapping for us, even though
-		 * the address is < ioremap_base.  This is necessary
-		 * since we want our PCI IO space to have contiguous
-		 * virtual addresses and I think it's worse to have
-		 * calls to map_page() here.
-		 * -- Cort
-		 */
-		unsigned long hold = ioremap_base;
-		ioremap_base = 0;
-		__ioremap(0x90000000, 0x10000000, _PAGE_NO_CACHE);
-		ioremap_base = hold;
-#endif		
+		struct property *p;
+		device = find_devices("rtas");
+		for ( p = device->properties;
+		      strncmp(p->name, "rtas-event-scan-rate", 20) && p ;
+		      p = p->next )
+			/* nothing */ ;
+		if ( p && *(unsigned long *)p->value )
+		{
+			rtas_event_scan_rate = (HZ/(*(unsigned long *)p->value)*30)-1;
+			rtas_event_scan_ct = 1;
+			printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
+			       *(unsigned long *)p->value, rtas_event_scan_rate );
+		}
X 	}
X }
X 
X void
+chrp_event_scan(void)
+{
+	unsigned char log[1024];
+	if ( rtas_event_scan_rate && (rtas_event_scan_ct-- <= 0) )
+	{
+		call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 );
+		rtas_event_scan_ct = rtas_event_scan_rate;
+	}
+}
+	
+void
X chrp_restart(char *cmd)
X {
-#if 0
-	extern unsigned int rtas_entry, rtas_data, rtas_size;
X 	printk("RTAS system-reboot returned %d\n",
X 	       call_rtas("system-reboot", 0, 1, NULL));
-	printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
-	       rtas_entry,rtas_data,rtas_size);
X 	for (;;);
-#else
-	printk("System Halted\n");
-	while(1);
-#endif
X }
X 
X void
X chrp_power_off(void)
X {
-	/* RTAS doesn't seem to work on Longtrail.
-	   For now, do it the same way as the PReP. */
-#if 0
-	extern unsigned int rtas_entry, rtas_data, rtas_size;
+	/* allow power on only with power button press */
+#define	PWR_FIELD(x) (0x8000000000000000 >> ((x)-96))
X 	printk("RTAS power-off returned %d\n",
-	       call_rtas("power-off", 2, 1, NULL, 0, 0));
-	printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
-	       rtas_entry,rtas_data,rtas_size);
+	       call_rtas("power-off", 2, 1, NULL,
+			 ((PWR_FIELD(96)|PWR_FIELD(97))>>32)&0xffffffff,
+			 (PWR_FIELD(96)|PWR_FIELD(97))&0xffffffff));
+#undef PWR_FIELD	
X 	for (;;);
-#else
-	chrp_restart(NULL);
-#endif
X }
X 
X void
X chrp_halt(void)
X {
-	chrp_restart(NULL);
+	chrp_power_off();
X }
X 
X u_int
@@ -668,5 +665,21 @@
X         ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
X 
X         ppc_ide_md.io_base = _IO_BASE;
-#endif		
+#endif
+	/*
+	 * Print the banner, then scroll down so boot progress
+	 * can be printed.  -- Cort 
+	 */
+	chrp_progress("Linux/PPC "UTS_RELEASE"\n");
+}
+
+void chrp_progress(char *s)
+{
+	extern unsigned int rtas_data;
+	
+	if ( (_machine != _MACH_chrp) || !rtas_data )
+		return;
+	call_rtas( "display-character", 1, 1, NULL, '\r' );
+	while ( *s )
+		call_rtas( "display-character", 1, 1, NULL, *s++ );
X }
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.2.9/linux/arch/ppc/kernel/head.S	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/head.S	Fri Jun  4 13:30:47 1999
@@ -1,7 +1,7 @@
X /*
X  *  arch/ppc/kernel/head.S
X  *
- *  $Id: head.S,v 1.130 1999/05/09 19:16:43 cort Exp $
+ *  $Id: head.S,v 1.130.2.1 1999/05/29 19:09:59 cort Exp $
X  *
X  *  PowerPC version 
X  *    Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)
@@ -97,18 +97,32 @@
X 	bdnz	0b
X #endif
X 
+#ifdef CONFIG_PPC64
+#define LOAD_BAT(n, offset, reg, RA, RB) \
+	ld	RA,offset+0(reg);	\
+	ld	RB,offset+8(reg);	\
+	mtspr	IBAT##n##U,RA;		\
+	mtspr	IBAT##n##L,RB;		\
+	ld	RA,offset+16(reg);	\
+	ld	RB,offset+24(reg);	\
+	mtspr	DBAT##n##U,RA;		\
+	mtspr	DBAT##n##L,RB;		\
+	
+#else /* CONFIG_PPC64 */
+	
X /* 601 only have IBAT cr0.eq is set on 601 when using this macro */ 
X #define LOAD_BAT(n, offset, reg, RA, RB) \
-	lwz	RA,offset+0(reg); \
+	lwz	RA,offset+0(reg);	\
X 	lwz	RB,offset+4(reg);	\
-	mtspr	IBAT##n##U,RA;	\
-	mtspr	IBAT##n##L,RB;	\
-	beq	1f;		\
+	mtspr	IBAT##n##U,RA;		\
+	mtspr	IBAT##n##L,RB;		\
+	beq	1f;			\
X 	lwz	RA,offset+8(reg);	\
X 	lwz	RB,offset+12(reg);	\
-	mtspr	DBAT##n##U,RA;	\
-	mtspr	DBAT##n##L,RB;	\
-1:	 
+	mtspr	DBAT##n##U,RA;		\
+	mtspr	DBAT##n##L,RB;		\
+1:	
+#endif /* CONFIG_PPC64 */	 
X 
X #ifndef CONFIG_APUS
X #define tophys(rd,rs,rt)	addis	rd,rs,-KERNELBASE@h
@@ -206,6 +220,16 @@
X 	
X 	.globl	__start
X __start:
+#ifdef CONFIG_PPC64
+/* 
+ * Go into 32-bit mode to boot.  OF should do this for
+ * us already but just in case...
+ * -- Cort 
+ */
+	mfmsr	r10
+	clrldi	r10,r10,3
+	mtmsr	r10
+#endif	
X /*
X  * We have to do any OF calls before we map ourselves to KERNELBASE,
X  * because OF may have I/O devices mapped in in that area
@@ -226,10 +250,11 @@
X  * of RAM to KERNELBASE.  From this point on we can't safely
X  * call OF any more.
X  */
+	lis	r11,KERNELBASE@h
+#ifndef CONFIG_PPC64
X 	mfspr	r9,PVR
X 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
X 	cmpi	0,r9,1
-	lis	r11,KERNELBASE@h
X 	bne	4f
X 	ori	r11,r11,4		/* set up BAT registers for 601 */
X 	li	r8,0x7f			/* valid, block length = 8MB */
@@ -240,6 +265,7 @@
X 	mtspr	IBAT1U,r9
X 	mtspr	IBAT1L,r10
X 	b	5f
+#endif /* CONFIG_PPC64 */
X 4:
X #ifdef CONFIG_APUS
X 	ori	r11,r11,BL_8M<<2|0x2	/* set up an 8MB mapping */
@@ -248,9 +274,17 @@
X 	lwz	r8,0(r8)
X 	addis	r8,r8,KERNELBASE@h
X 	addi	r8,r8,2
-#else
+#else	
X 	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */
X 	li	r8,2			/* R/W access */
+#ifdef CONFIG_PPC64
+	/* clear out the high 32 bits in the BAT */
+	clrldi	r11,r11,32
+	clrldi	r8,r8,32
+	/* turn off the pagetable mappings just in case */
+	clrldi	r16,r16,63
+	mtsdr1	r16
+#else /* CONFIG_PPC64 */
X 	/* 
X 	 * allow secondary cpus to get at all of ram in early bootup
X 	 * since their init_task may be up there -- Cort
@@ -268,6 +302,7 @@
X 	mtspr	DBAT2U,r21		/* bit in upper BAT register */
X 	mtspr	IBAT2L,r28
X 	mtspr	IBAT2U,r21
+#endif /* CONFIG_PPC64 */
X #endif
X 	mtspr	DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
X 	mtspr	DBAT0U,r11		/* bit in upper BAT register */
@@ -1246,7 +1281,7 @@
X 	eieio
X 	lis	r2,hash_table_lock@h
X 	ori	r2,r2,hash_table_lock@l
-	tophys(r2,r2,r6)
+ 	tophys(r2,r2,r6)
X 	lis	r6,100000000@h
X 	mtctr	r6
X 	lwz	r0,PROCESSOR-TSS(r5)
@@ -1294,6 +1329,11 @@
X 	stw	r6,0(r2)		/* update PTE (accessed/dirty bits) */
X 
X 	/* Convert linux-style PTE to low word of PPC-style PTE */
+#ifdef CONFIG_PPC64
+	/* clear the high 32 bits just in case */
+	clrldi	r6,r6,32
+	clrldi	r4,r4,32
+#endif /* CONFIG_PPC64 */
X 	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
X 	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
X 	ori	r4,r4,0xe04		/* clear out reserved bits */
@@ -1301,16 +1341,34 @@
X 
X 	/* Construct the high word of the PPC-style PTE */
X 	mfsrin	r5,r3			/* get segment reg for segment */
+#ifdef CONFIG_PPC64
+	sldi	r5,r5,12
+#else /* CONFIG_PPC64 */
X 	rlwinm	r5,r5,7,1,24		/* put VSID in 0x7fffff80 bits */
+#endif /* CONFIG_PPC64 */
+	
X #ifndef __SMP__				/* do this later for SMP */
+#ifdef CONFIG_PPC64
+	ori	r5,r5,1			/* set V (valid) bit */
+#else /* CONFIG_PPC64 */
X 	oris	r5,r5,0x8000		/* set V (valid) bit */
+#endif /* CONFIG_PPC64 */
X #endif
+	
+#ifdef CONFIG_PPC64
+/* XXX:	 does this insert the api correctly? -- Cort */
+	rlwimi	r5,r3,17,21,25		/* put in API (abbrev page index) */
+#else /* CONFIG_PPC64 */
X 	rlwimi	r5,r3,10,26,31		/* put in API (abbrev page index) */
-
+#endif /* CONFIG_PPC64 */
X 	/* Get the address of the primary PTE group in the hash table */
X 	.globl	hash_page_patch_A
X hash_page_patch_A:
X 	lis	r4,Hash_base@h		/* base address of hash table */
+#ifdef CONFIG_PPC64
+	/* just in case */
+	clrldi	r4,r4,32
+#endif	
X 	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
X 	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
X 	xor	r4,r4,r0		/* make primary hash */
@@ -1799,7 +1857,11 @@
X  */
X #ifndef CONFIG_8xx
X 	lis	r6,_SDR1@ha
+#ifdef CONFIG_PPC64	
+	ld	r6,_SDR1@l(r6)
+#else
X 	lwz	r6,_SDR1@l(r6)
+#endif		
X #else
X 	/* The right way to do this would be to track it down through
X 	 * init's TSS like the context switch code does, but this is
@@ -1828,6 +1890,14 @@
X #endif
X #ifndef CONFIG_8xx
X 	mtspr	SDR1,r6
+#ifdef CONFIG_PPC64
+	/* clear the v bit in the ASR so we can
+	 * behave as if we have segment registers 
+	 * -- Cort
+	 */
+	clrldi	r6,r6,63
+	mtasr	r6
+#endif /* CONFIG_PPC64 */
X 	li	r0,16		/* load up segment register values */
X 	mtctr	r0		/* for context 0 */
X 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
@@ -1844,10 +1914,17 @@
X 	lis	r3,BATS@ha
X 	addi	r3,r3,BATS@l
X 	tophys(r3,r3,r4)
+#ifdef CONFIG_PPC64
+	LOAD_BAT(0,0,r3,r4,r5)
+	LOAD_BAT(1,32,r3,r4,r5)
+	LOAD_BAT(2,64,r3,r4,r5)
+	LOAD_BAT(3,96,r3,r4,r5)
+#else /* CONFIG_PPC64 */
X 	LOAD_BAT(0,0,r3,r4,r5)
X 	LOAD_BAT(1,16,r3,r4,r5)
X 	LOAD_BAT(2,32,r3,r4,r5)
X 	LOAD_BAT(3,48,r3,r4,r5)
+#endif /* CONFIG_PPC64 */
X #endif /* CONFIG_8xx */
X /* Set up for using our exception vectors */
X 	/* ptr to phys current tss */
@@ -2538,7 +2615,6 @@
X  */
X 	.globl	enter_rtas
X enter_rtas:
-	stwu	r1,-16(r1)
X 	mflr	r0
X 	stw	r0,20(r1)
X 	lis	r4,rtas_data@ha
@@ -2559,7 +2635,6 @@
X 	andi.	r9,r9,MSR_ME|MSR_RI
X 	sync			/* disable interrupts so SRR0/1 */
X 	mtmsr	r0		/* don't get trashed */
-	li	r6,0	
X 	mtlr	r6
X 	mtspr	SPRG2,r7
X 	mtspr	SRR0,r8
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.2.9/linux/arch/ppc/kernel/idle.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/idle.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: idle.c,v 1.61 1999/03/18 04:15:45 cort Exp $
+ * $Id: idle.c,v 1.61.2.1 1999/05/29 19:10:02 cort Exp $
X  *
X  * Idle daemon for PowerPC.  Idle daemon will handle any action
X  * that needs to be taken when the system becomes idle.
@@ -50,6 +50,7 @@
X 	/* endless loop with no priority at all */
X 	current->priority = 0;
X 	current->counter = -100;
+	init_idle();	
X 	for (;;)
X 	{
X 		__sti();
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.2.9/linux/arch/ppc/kernel/irq.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/irq.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: irq.c,v 1.105 1999/03/25 19:51:51 cort Exp $
+ * $Id: irq.c,v 1.105.2.1 1999/05/29 19:10:05 cort Exp $
X  *
X  *  arch/ppc/kernel/irq.c
X  *
@@ -65,7 +65,6 @@
X void enable_irq(unsigned int irq_nr);
X void disable_irq(unsigned int irq_nr);
X 
-/* Fixme - Need to figure out a way to get rid of this - Corey */
X volatile unsigned char *chrp_int_ack_special;
X 
X #ifdef CONFIG_APUS
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.2.9/linux/arch/ppc/kernel/misc.S	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/misc.S	Fri Jun  4 13:30:47 1999
@@ -649,15 +649,6 @@
X         blr
X 
X /*
- * Fetch the current SR register
- *   get_SR(int index)
- */
-_GLOBAL(get_SR)
-	mfsrin	r4,r3
-	mr	r3,r4
-	blr
-
-/*
X  * Create a kernel thread
X  *   __kernel_thread(flags, fn, arg)
X  */
@@ -875,7 +866,11 @@
X 	.long sys_getresuid	/* 165 */
X 	.long sys_query_module
X 	.long sys_poll
+#ifdef CONFIG_NFS	
X 	.long sys_nfsservctl
+#else
+	.long sys_ni_syscall
+#endif		
X 	.long sys_setresgid
X 	.long sys_getresgid	/* 170 */
X 	.long sys_prctl
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.2.9/linux/arch/ppc/kernel/prep_pci.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/prep_pci.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: prep_pci.c,v 1.33 1999/05/09 20:15:54 cort Exp $
+ * $Id: prep_pci.c,v 1.35 1999/05/10 23:31:03 cort Exp $
X  * PReP pci functions.
X  * Originally by Gary Thomas
X  * rewritten and updated by Cort Dougan (co...@cs.nmt.edu)
@@ -38,6 +38,8 @@
X /* Used for Motorola to store system config register */
X static unsigned long	*ProcInfo;
X 
+extern void chrp_do_IRQ(struct pt_regs *,int , int);
+
X /* Tables for known hardware */   
X 
X /* Motorola PowerStackII - Utah */
@@ -731,6 +733,8 @@
X 	OpenPIC_InitSenses = mvme2600_openpic_initsenses;
X 	OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
X 
+	ppc_md.do_IRQ = chrp_do_IRQ;
+	
X 	/* If raven is present on Motorola store the system config register
X 	 * for later use.
X 	 */
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.2.9/linux/arch/ppc/kernel/prep_setup.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Fri Jun  4 13:30:47 1999
@@ -249,7 +249,7 @@
X 		ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
X 		break;
X 	case _PREP_Radstone:
-		ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
+		ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
X 
X 		/*
X 		 * Determine system type
@@ -767,10 +767,8 @@
X 	ppc_md.get_cpuinfo    = prep_get_cpuinfo;
X 	ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
X 	ppc_md.init_IRQ       = prep_init_IRQ;
-	if ( !OpenPIC )
-		ppc_md.do_IRQ         = prep_do_IRQ;
-	else
-		ppc_md.do_IRQ         = chrp_do_IRQ;
+	/* this gets changed later on if we have an OpenPIC -- Cort */
+	ppc_md.do_IRQ         = prep_do_IRQ;
X 	ppc_md.init           = NULL;
X 
X 	ppc_md.restart        = prep_restart;
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.2.9/linux/arch/ppc/kernel/prom.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/prom.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: prom.c,v 1.54 1999/05/10 04:43:46 cort Exp $
+ * $Id: prom.c,v 1.54.2.1 1999/05/29 19:10:12 cort Exp $
X  *
X  * Procedures for interfacing to the Open Firmware PROM on
X  * Power Macintosh computers.
@@ -24,6 +24,7 @@
X #include <asm/io.h>
X #include <asm/smp.h>
X #include <asm/bootx.h>
+#include <asm/system.h>
X 
X /*
X  * Properties whose value is longer than this get excluded from our
@@ -412,6 +413,9 @@
X 	mem = copy_device_tree(mem, mem + (1<<20));
X 	prom_print(RELOC("done\n"));
X 
+
+	RELOC(klimit) = (char *) (mem - offset);
+	
X 	prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
X 	if (prom_rtas != (void *) -1) {
X 		RELOC(rtas_size) = 0;
@@ -421,9 +425,19 @@
X 		if (RELOC(rtas_size) == 0) {
X 			RELOC(rtas_data) = 0;
X 		} else {
-			mem = (mem + 4095) & -4096; /* round to page bdry */
+			/*
+			 * We do _not_ want the rtas_data inside the klimit
+			 * boundry since it'll be squashed when we do the
+			 * relocate of the kernel on chrp right after prom_init()
+			 * in head.S.  So, we just pick a spot in memory.
+			 * -- Cort
+			 */
+#if 0
+			mem = (mem + 4095) & -4096;
X 			RELOC(rtas_data) = mem + KERNELBASE;
X 			mem += RELOC(rtas_size);
+#endif
+			RELOC(rtas_data) = (6<<20) + KERNELBASE;
X 		}
X 		prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
X 		{
@@ -448,7 +462,7 @@
X 		else
X 			prom_print(RELOC(" done\n"));
X 	}
-	RELOC(klimit) = (char *) (mem - offset);
+
X #ifdef CONFIG_SMP
X 	/*
X 	 * With CHRP SMP we need to use the OF to start the other
@@ -1289,7 +1303,7 @@
X 	  unsigned long *outputs, ...)
X {
X 	va_list list;
-	int i;
+	int i, s;
X 	struct device_node *rtas;
X 	int *tokp;
X 	union {
@@ -1305,16 +1319,19 @@
X 		printk(KERN_ERR "No RTAS service called %s\n", service);
X 		return -1;
X 	}
-	u.words[0] = __pa(*tokp);
+	u.words[0] = *tokp;
X 	u.words[1] = nargs;
X 	u.words[2] = nret;
X 	va_start(list, outputs);
X 	for (i = 0; i < nargs; ++i)
X 		u.words[i+3] = va_arg(list, unsigned long);
X 	va_end(list);
+	
+	s = _disable_interrupts();
X 	spin_lock(&rtas_lock);
X 	enter_rtas((void *)__pa(&u));
X 	spin_unlock(&rtas_lock);
+	_enable_interrupts(s);
X 	if (nret > 1 && outputs != NULL)
X 		for (i = 0; i < nret-1; ++i)
X 			outputs[i] = u.words[i+nargs+4];
@@ -1326,8 +1343,7 @@
X abort()
X {
X #ifdef CONFIG_XMON
-	extern void xmon(void *);
-	xmon(0);
+	xmon(NULL);
X #endif
X 	prom_exit();
X }
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.2.9/linux/arch/ppc/kernel/ptrace.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/ptrace.c	Fri Jun  4 13:30:47 1999
@@ -330,8 +330,12 @@
X 		if ((!child->dumpable ||
X 		    (current->uid != child->euid) ||
X 		    (current->uid != child->uid) ||
+		    (current->uid != child->suid) ||
X 	 	    (current->gid != child->egid) ||
-	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+	 	    (current->gid != child->gid) ||
+		    (current->gid != child->sgid) ||
+		    (!cap_issubset(child->cap_permitted, current->cap_permitted)))
+		    && !capable(CAP_SYS_PTRACE))
X 			goto out;
X 		/* the same process cannot be attached many times */
X 		if (child->flags & PF_PTRACED)
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- v2.2.9/linux/arch/ppc/kernel/residual.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/residual.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: residual.c,v 1.14 1998/10/11 17:38:10 cort Exp $
+ * $Id: residual.c,v 1.14.2.1 1999/05/29 19:10:17 cort Exp $
X  *
X  * Code to deal with the PReP residual data.
X  *
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.2.9/linux/arch/ppc/kernel/setup.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/setup.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: setup.c,v 1.132 1999/03/24 00:32:19 cort Exp $
+ * $Id: setup.c,v 1.132.2.1 1999/06/03 03:03:45 paulus Exp $
X  * Common prep/pmac/chrp boot and setup code.
X  */
X 
@@ -375,7 +375,6 @@
X 			else
X 			{
X 				_machine = _MACH_Pmac;
-				is_prep = 1;
X 			}
X 		}
X 
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.2.9/linux/arch/ppc/kernel/smp.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/smp.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: smp.c,v 1.49 1999/03/18 04:16:31 cort Exp $
+ * $Id: smp.c,v 1.49.2.1 1999/05/29 19:10:20 cort Exp $
X  *
X  * Smp support for ppc.
X  *
@@ -388,9 +388,12 @@
X 
X void __init smp_callin(void)
X {
+	int i;
+	
X 	printk("SMP %d: smp_callin()\n",current->processor);
X         smp_store_cpu_info(current->processor);
X 	set_dec(decrementer_count);
+	
X #if 0
X 	current->mm->mmap->vm_page_prot = PAGE_SHARED;
X 	current->mm->mmap->vm_start = PAGE_OFFSET;
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.2.9/linux/arch/ppc/kernel/softemu8xx.c	Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/softemu8xx.c	Fri Jun  4 13:30:47 1999
@@ -34,6 +34,7 @@
X 
X /* Eventually we may need a look-up table, but this works for now.
X */
+#define LFS	48
X #define LFD	50
X #define LFDU	51
X #define STFD	54
@@ -82,6 +83,12 @@
X 			retval = EFAULT;
X 		else
X 			regs->gpr[idxreg] = (uint)ea;
+		break;
+	case LFS:
+		sdisp = (instword & 0xffff);
+		ea = (uint *)(regs->gpr[idxreg] + sdisp);
+		if (copy_from_user(ip, ea, sizeof(float)))
+			retval = EFAULT;
X 		break;
X 	case STFD:
X 		/* this is a 16 bit quantity that is sign extended
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.2.9/linux/arch/ppc/kernel/syscalls.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/syscalls.c	Fri Jun  4 13:30:47 1999
@@ -182,18 +182,14 @@
X 	int fd[2];
X 	int error;
X 
-	error = verify_area(VERIFY_WRITE, fildes, 8);
-	if (error)
-		return error;
X 	lock_kernel();
X 	error = do_pipe(fd);
X 	unlock_kernel();
-	if (error)
-		return error;
-	if (__put_user(fd[0],0+fildes)
-	    || __put_user(fd[1],1+fildes))
-		return -EFAULT;	/* should we close the fds? */
-	return 0;
+	if (!error) {
+		if (copy_to_user(fildes, fd, 2*sizeof(int)))
+			error = -EFAULT;
+	}
+	return error;
X }
X 
X asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
@@ -205,15 +201,12 @@
X 
X 	lock_kernel();
X 	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
+		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
X 			goto out;
X 	}
X 	
X 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
X 	ret = do_mmap(file, addr, len, prot, flags, offset);
-	if (file)
-		fput(file);
X out:
X 	unlock_kernel();
X 	return ret;
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.2.9/linux/arch/ppc/kernel/time.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/time.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: time.c,v 1.47 1999/03/18 05:11:11 cort Exp $
+ * $Id: time.c,v 1.47.2.1 1999/05/29 19:10:23 cort Exp $
X  * Common time routines among all ppc machines.
X  *
X  * Written by Cort Dougan (co...@cs.nmt.edu) to merge
@@ -126,13 +126,17 @@
X 	smp_local_timer_interrupt(regs);
X #endif		
X 
-	/* Fixme - make this more generic - Corey */
X #ifdef CONFIG_APUS
X 	{
X 		extern void apus_heartbeat (void);
X 		apus_heartbeat ();
X 	}
X #endif
+#if defined(CONFIG_ALL_PPC) || defined(CONFIG_CHRP)
+	if ( _machine == _MACH_chrp )
+		chrp_event_scan();
+#endif	
+
X 	hardirq_exit(cpu);
X }
X 
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.2.9/linux/arch/ppc/kernel/traps.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/traps.c	Fri Jun  4 13:30:47 1999
@@ -79,7 +79,6 @@
X 		debugger(regs);
X #endif
X 		print_backtrace((unsigned long *)regs->gpr[1]);
-		instruction_dump((unsigned long *)regs->nip);
X 		panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
X 	}
X 	force_sig(signr, current);
@@ -127,7 +126,6 @@
X 		debugger(regs);
X #endif
X 		print_backtrace((unsigned long *)regs->gpr[1]);
-		instruction_dump((unsigned long *)regs->nip);
X 		panic("machine check");
X 	}
X 	_exception(SIGSEGV, regs);	
@@ -216,7 +214,6 @@
X #endif
X 	show_regs(regs);
X 	print_backtrace((unsigned long *)regs->gpr[1]);
-	instruction_dump((unsigned long *)regs->nip);
X 	panic("kernel stack overflow");
X }
X 
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.2.9/linux/arch/ppc/mm/fault.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/mm/fault.c	Fri Jun  4 13:30:47 1999
@@ -89,7 +89,6 @@
X 			printk("page fault in interrupt handler, addr=%lx\n",
X 			       address);
X 			show_regs(regs);
-			instruction_dump((unsigned long *)regs->nip);
X #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
X 			if (debugger_kernel_faults)
X 				debugger(regs);
@@ -176,7 +175,6 @@
X 	/* kernel has accessed a bad area */
X 	show_regs(regs);
X 	print_backtrace( (unsigned long *)regs->gpr[1] );
-	instruction_dump((unsigned long *)regs->nip);
X #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
X 	if (debugger_kernel_faults)
X 		debugger(regs);
diff -u --recursive --new-file v2.2.9/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.2.9/linux/arch/ppc/mm/init.c	Tue May 11 13:10:28 1999
+++ linux/arch/ppc/mm/init.c	Fri Jun  4 13:30:47 1999
@@ -1,5 +1,5 @@
X /*
- *  $Id: init.c,v 1.164 1999/05/05 17:33:55 cort Exp $
+ *  $Id: init.c,v 1.164.2.2 1999/06/03 03:03:53 paulus Exp $
X  *
X  *  PowerPC version 
X  *    Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)
@@ -371,7 +371,7 @@
X 	 * same virt address (and this is contiguous).
X 	 *  -- Cort
X 	 */
-	if ( (v = p_mapped_by_bats(addr)) /*&& p_mapped_by_bats(addr+(size-1))*/ )
+	if ( (v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
X 		goto out;
X #endif /* CONFIG_8xx */
X 	
@@ -402,7 +402,7 @@
X 	for (i = 0; i < size; i += PAGE_SIZE)
X 		map_page(&init_task, v+i, p+i, flags);
X out:	
-	return (void *) (v + (p & ~PAGE_MASK));
+	return (void *) (v + (addr & ~PAGE_MASK));
X }
X 
X void iounmap(void *addr)
@@ -1510,7 +1510,7 @@
X 	for (h = 256<<10; h < ramsize / 256 && h < 4<<20; h *= 2, Hash_mask++)
X 		;
X 	Hash_size = h;
-	Hash_mask << 10;  /* so setting _SDR1 works the same -- Cort */
+	Hash_mask <<= 10;  /* so setting _SDR1 works the same -- Cort */
X #else
X 	for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2)
X 		;
diff -u --recursive --new-file v2.2.9/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.2.9/linux/arch/sparc/defconfig	Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc/defconfig	Wed Jun  2 09:55:38 1999
@@ -62,6 +62,7 @@
X CONFIG_SUN_MOSTEK_RTC=y
X # CONFIG_SUN_BPP is not set
X # CONFIG_SUN_VIDEOPIX is not set
+CONFIG_SUN_AURORA=m
X 
X #
X # Linux/SPARC audio subsystem (EXPERIMENTAL)
diff -u --recursive --new-file v2.2.9/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.2.9/linux/arch/sparc/kernel/signal.c	Tue Mar 23 14:35:46 1999
+++ linux/arch/sparc/kernel/signal.c	Sun Jun 13 19:42:01 1999
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.91 1999/01/26 11:00:44 jj Exp $
+/*  $Id: signal.c,v 1.91.2.1 1999/06/14 00:36:13 davem Exp $
X  *  linux/arch/sparc/kernel/signal.c
X  *
X  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -1194,6 +1194,7 @@
X 			default:
X 				lock_kernel();
X 				sigaddset(¤t->signal, signr);
+				recalc_sigpending(current);
X 				current->flags |= PF_SIGNALED;
X 				do_exit(exit_code);
X 				/* NOT REACHED */
diff -u --recursive --new-file v2.2.9/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.2.9/linux/arch/sparc/kernel/sys_sunos.c	Sun Nov  8 14:02:45 1998
+++ linux/arch/sparc/kernel/sys_sunos.c	Wed Jun  2 09:55:38 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.94 1998/10/12 06:15:04 jj Exp $
+/* $Id: sys_sunos.c,v 1.94.2.1 1999/05/24 19:42:30 davem Exp $
X  * sys_sunos.c: SunOS specific syscall compatibility support.
X  *
X  * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -1198,7 +1198,7 @@
X 
X 	lock_kernel();
X 	ret = check_nonblock(sys_readv(fd,vector,count),fd);
-	lock_kernel();
+	unlock_kernel();
X 	return ret;
X }
X 
diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.2.9/linux/arch/sparc64/defconfig	Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc64/defconfig	Wed Jun  2 09:55:38 1999
@@ -68,6 +68,7 @@
X CONFIG_OBP_FLASH=m
X # CONFIG_SUN_BPP is not set
X # CONFIG_SUN_VIDEOPIX is not set
+CONFIG_SUN_AURORA=m
X 
X #
X # Linux/SPARC audio subsystem (EXPERIMENTAL)
diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.2.9/linux/arch/sparc64/kernel/ioctl32.c	Tue May 11 13:10:28 1999
+++ linux/arch/sparc64/kernel/ioctl32.c	Sun Jun 13 19:42:01 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.62 1999/05/01 09:17:44 davem Exp $
+/* $Id: ioctl32.c,v 1.62.2.1 1999/06/09 04:53:03 davem Exp $
X  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
X  *
X  * Copyright (C) 1997  Jakub Jelinek  (j...@sunsite.mff.cuni.cz)
@@ -37,6 +37,7 @@
X #include <linux/fb.h>
X #include <linux/ext2_fs.h>
X #include <linux/videodev.h>
+#include <linux/netdevice.h>
X 
X #include <scsi/scsi.h>
X /* Ugly hack. */
@@ -417,6 +418,23 @@
X         __kernel_caddr_t32  ifcbuf;
X };
X 
+static int dev_ifname32(unsigned int fd, unsigned long arg)
+{
+	struct device *dev;
+	struct ifreq32 ifr32;
+	int err;
+
+	if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+
+	dev = dev_get_by_index(ifr32.ifr_ifindex);
+	if (!dev)
+		return -ENODEV;
+
+	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
+	return (err ? -EFAULT : 0);
+}
+
X static inline int dev_ifconf(unsigned int fd, unsigned long arg)
X {
X 	struct ifconf32 ifc32;
@@ -1687,6 +1705,10 @@
X 		goto out;
X 	}
X 	switch (cmd) {
+	case SIOCGIFNAME:
+		error = dev_ifname32(fd, arg);
+		goto out;
+
X 	case SIOCGIFCONF:
X 		error = dev_ifconf(fd, arg);
X 		goto out;
diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.2.9/linux/arch/sparc64/kernel/setup.c	Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc64/kernel/setup.c	Sat May 29 11:10:15 1999
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $
+/*  $Id: setup.c,v 1.43.2.1 1999/05/28 02:18:13 davem Exp $
X  *  linux/arch/sparc64/kernel/setup.c
X  *
X  *  Copyright (C) 1995,1996  David S. Miller (da...@caip.rutgers.edu)
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 04'
echo 'File patch-2.2.10 is continued in part 05'
echo 05 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 18 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 18; 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
+#define UART_RX_SIZE_HI   0x05
+#define UART_RX_SIZE_LO   0x06
+
+#define UART_1152     0x01<<7
+#define UART_CRC      0x01<<6
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[10];
+	int head;
+	int tail;
+	int len;
+};
+
+/* Private data for each instance */
+struct ircc_cb {
+	struct st_fifo st_fifo;
+
+	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
+	int tx_len;          /* Number of frames in tx_buff */
+
+	struct irda_device idev;
+};
+
+#endif
diff -u --recursive --new-file v2.2.9/linux/include/net/irda/smc_ircc.h linux/include/net/irda/smc_ircc.h
--- v2.2.9/linux/include/net/irda/smc_ircc.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/smc_ircc.h	Wed Dec 31 16:00:00 1969
@@ -1,123 +0,0 @@
-#if 0
-static char *rcsid = "$Id: smc_ircc.h,v 1.5 1998/07/27 01:25:29 ratbert Exp $";
-#endif
-
-#ifndef SMC_IRCC_H
-#define SMC_IRCC_H
-
-#define FIR_XMIT	1
-#define FIR_RECEIVE	2
-#define SIR_XMIT	3
-#define SIR_RECEIVE	4
-
-#define MASTER			0x07
-#define MASTER_POWERDOWN	1<<7
-#define MASTER_RESET		1<<6
-#define MASTER_INT_EN		1<<5
-#define MASTER_ERROR_RESET	1<<4
-
-/* Register block 0 */
-
-#define IIR	0x01
-#define IER	0x02
-#define LSR	0x03
-#define LCR_A	0x04
-#define LCR_B	0x05
-#define BSR	0x06
-
-#define IIR_ACTIVE_FRAME	1<<7
-#define IIR_EOM 		1<<6
-#define IIR_RAW_MODE		1<<5
-#define IIR_FIFO		1<<4
-
-#define IER_ACTIVE_FRAME	1<<7
-#define IER_EOM 		1<<6
-#define IER_RAW_MODE		1<<5
-#define IER_FIFO		1<<4
-
-#define LSR_UNDER_RUN		1<<7
-#define LSR_OVER_RUN		1<<6
-#define LSR_FRAME_ERROR 	1<<5
-#define LSR_SIZE_ERROR		1<<4
-#define LSR_CRC_ERROR		1<<3
-#define LSR_FRAME_ABORT 	1<<2
-
-#define LCR_A_FIFO_RESET        1<<7
-#define LCR_A_FAST              1<<6
-#define LCR_A_GP_DATA           1<<5
-#define LCR_A_RAW_TX            1<<4
-#define LCR_A_RAW_RX            1<<3
-#define LCR_A_ABORT             1<<2
-#define LCR_A_DATA_DONE         1<<1
-
-#define LCR_B_SCE_MODE_DISABLED 	0x00<<6
-#define LCR_B_SCE_MODE_TRANSMIT 	0x01<<6
-#define LCR_B_SCE_MODE_RECEIVE		0x02<<6
-#define LCR_B_SCE_MODE_UNDEFINED	0x03<<6
-#define LCR_B_SIP_ENABLE		1<<5
-#define LCR_B_BRICK_WALL		1<<4
-
-#define BSR_NOT_EMPTY	1<<7
-#define BSR_FIFO_FULL	1<<6
-#define BSR_TIMEOUT	1<<5
-
-/* Register block 1 */
-
-#define SCE_CFG_A	0x00
-#define SCE_CFG_B	0x01
-#define FIFO_THRESHOLD	0x02
-
-#define CFG_A_AUX_IR		0x01<<7
-#define CFG_A_HALF_DUPLEX	0x01<<2
-#define CFG_A_TX_POLARITY	0x01<<1
-#define CFG_A_RX_POLARITY	0x01
-
-#define CFG_A_COM		0x00<<3
-#define CFG_A_IRDA_SIR_A	0x01<<3
-#define CFG_A_ASK_SIR		0x02<<3
-#define CFG_A_IRDA_SIR_B	0x03<<3
-#define CFG_A_IRDA_HDLC 	0x04<<3
-#define CFG_A_IRDA_4PPM 	0x05<<3
-#define CFG_A_CONSUMER		0x06<<3
-#define CFG_A_RAW_IR		0x07<<3
-#define CFG_A_OTHER		0x08<<3
-
-#define IR_HDLC			0x04
-#define IR_4PPM			0x01
-#define IR_CONSUMER		0x02
-
-#define CFG_B_LOOPBACK		0x01<<5
-#define CFG_B_LPBCK_TX_CRC	0x01<<4
-#define CFG_B_NOWAIT		0x01<<3
-#define CFB_B_STRING_MOVE	0x01<<2
-#define CFG_B_DMA_BURST 	0x01<<1
-#define CFG_B_DMA_ENABLE	0x01
-
-#define CFG_B_MUX_COM		0x00<<6
-#define CFG_B_MUX_IR		0x01<<6
-#define CFG_B_MUX_AUX		0x02<<6
-#define CFG_B_INACTIVE		0x03<<6
-
-/* Register block 2 - Consumer IR - not used */
-
-/* Register block 3 - Identification Registers! */
-
-#define SMSC_ID_HIGH	0x00   /* 0x10 */
-#define SMSC_ID_LOW	0x01   /* 0xB8 */
-#define CHIP_ID 	0x02   /* 0xF1 */
-#define VERSION_NUMBER	0x03   /* 0x01 */
-#define HOST_INTERFACE	0x04   /* low 4 = DMA, high 4 = IRQ */
-
-/* Register block 4 - IrDA */
-#define IR_CONTROL        0x00
-#define BOF_COUNT_LO      0x01
-#define BRICK_WALL_CNT_LO 0x02
-#define BRICK_TX_CNT_HI   0x03
-#define TX_DATA_SIZE_LO   0x04
-#define RX_DATA_SIZE_HI   0x05
-#define RX_DATA_SIZE_LO   0x06
-
-#define SELECT_1152     0x01<<7
-#define CRC_SELECT      0x01<<6
-
-#endif
diff -u --recursive --new-file v2.2.9/linux/include/net/irda/toshoboe.h linux/include/net/irda/toshoboe.h
--- v2.2.9/linux/include/net/irda/toshoboe.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/toshoboe.h	Sun May 30 10:17:03 1999
@@ -0,0 +1,165 @@
+/*********************************************************************
+ *                
+ * Filename:      toshoboe.h
+ * Version:       0.1
+ * Description:   Driver for the Toshiba OBOE (or type-O)
+ *                FIR Chipset. 
+ * Status:        Experimental.
+ * Author:        James McKenzie <ja...@fishsoup.dhs.org>
+ * Created at:    Sat May 8  12:35:27 1999
+ * 
+ *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither James McKenzie nor Cambridge University admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Applicable Models : Libretto 100CT. and many more
+ *
+ ********************************************************************/
+
+/*
+ * $Log: toshoboe.h,v $
+ * Revision 1.2  1999/05/09 01:43:08  root
+ * *** empty log message ***
+ *
+ * Revision 1.1  1999/05/09 01:25:58  root
+ * Initial revision
+ *
+ */
+
+#ifndef TOSHOBOE_H
+#define TOSHOBOE_H
+
+/* Registers */
+/*Receive and transmit task registers (read only) */
+#define OBOE_RCVT	(0x00+(self->base))
+#define OBOE_XMTT	(0x01+(self->base))
+#define OBOE_XMTT_OFFSET	0x40
+
+/*Page pointers to the TaskFile structure */
+#define OBOE_TFP2	(0x02+(self->base))
+#define OBOE_TFP0	(0x04+(self->base))
+#define OBOE_TFP1	(0x05+(self->base))
+
+/*Dunno */
+#define OBOE_REG_3	(0x03+(self->base))
+
+/*Number of tasks to use in Xmit and Recv queues */
+#define OBOE_NTR	(0x07+(self->base))
+#define OBOE_NTR_XMIT4	0x00
+#define OBOE_NTR_XMIT8	0x10
+#define OBOE_NTR_XMIT16	0x30
+#define OBOE_NTR_XMIT32	0x70
+#define OBOE_NTR_XMIT64	0xf0
+#define OBOE_NTR_RECV4	0x00
+#define OBOE_NTR_RECV8	0x01
+#define OBOE_NTR_RECV6	0x03
+#define OBOE_NTR_RECV32	0x07
+#define OBOE_NTR_RECV64	0x0f
+
+/* Dunno */
+#define OBOE_REG_9	(0x09+(self->base))
+
+/* Interrupt Status Register */
+#define OBOE_ISR	(0x0c+(self->base))
+#define OBOE_ISR_TXDONE	0x80
+#define OBOE_ISR_RXDONE	0x40
+#define OBOE_ISR_20	0x20
+#define OBOE_ISR_10	0x10
+#define OBOE_ISR_8	0x08         /*This is collision or parity or something */
+#define OBOE_ISR_4	0x08
+#define OBOE_ISR_2	0x08
+#define OBOE_ISR_1	0x08
+
+/*Dunno */
+#define OBOE_REG_D	(0x0d+(self->base))
+
+/*Register Lock Register */
+#define OBOE_LOCK	((self->base)+0x0e)
+
+
+
+/*Speed control registers */
+#define OBOE_PMDL	(0x10+(self->base))
+#define OBOE_PMDL_SIR	0x18
+#define OBOE_PMDL_MIR	0xa0
+#define OBOE_PMDL_FIR	0x40
+
+#define OBOE_SMDL	(0x18+(self->base))
+#define OBOE_SMDL_SIR	0x20
+#define OBOE_SMDL_MIR	0x01
+#define OBOE_SMDL_FIR	0x0f
+
+#define OBOE_UDIV	(0x19+(self->base))
+
+/*Dunno */
+#define OBOE_REG_11	(0x11+(self->base))
+
+/*Chip Reset Register */
+#define OBOE_RST	(0x15+(self->base))
+#define OBOE_RST_WRAP	0x8
+
+/*Dunno */
+#define OBOE_REG_1A	(0x1a+(self->base))
+#define OBOE_REG_1B	(0x1b+(self->base))
+
+/* The PCI ID of the OBOE chip */
+#ifndef PCI_DEVICE_ID_FIR701
+#define PCI_DEVICE_ID_FIR701 	0x0701
+#endif
+
+typedef unsigned int dword;
+typedef unsigned short int word;
+typedef unsigned char byte;
+typedef dword Paddr;
+
+struct OboeTask
+  {
+    __u16 len;
+    __u8 unused;
+    __u8 control;
+    __u32 buffer;
+  };
+
+#define OBOE_NTASKS 64
+
+struct OboeTaskFile
+  {
+    struct OboeTask recv[OBOE_NTASKS];
+    struct OboeTask xmit[OBOE_NTASKS];
+  };
+
+#define OBOE_TASK_BUF_LEN (sizeof(struct OboeTaskFile) << 1)
+
+/*These set the number of slots in use */
+#define TX_SLOTS	4
+#define RX_SLOTS	4
+
+/* You need also to change this, toshiba uses 4,8 and 4,4 */
+/* It makes no difference if you are only going to use ONETASK mode */
+/* remember each buffer use XX_BUF_SZ more _PHYSICAL_ memory */
+#define OBOE_NTR_VAL 	(OBOE_NTR_XMIT4 | OBOE_NTR_RECV4)
+
+struct toshoboe_cb
+  {
+    struct irda_device idev;    /*IRDA device */
+    struct pci_dev *pdev;       /*PCI device */
+    int base;                   /*IO base */
+    int txpending;              /*how many tx's are pending */
+    int txs, rxs;               /*Which slots are we at  */
+    void *taskfilebuf;          /*The unaligned taskfile buffer */
+    struct OboeTaskFile *taskfile;  /*The taskfile   */
+    void *xmit_bufs[TX_SLOTS];  /*The buffers   */
+    void *recv_bufs[RX_SLOTS];
+  };
+
+
+#endif
+
+
diff -u --recursive --new-file v2.2.9/linux/include/net/irda/w83977af_ir.h linux/include/net/irda/w83977af_ir.h
--- v2.2.9/linux/include/net/irda/w83977af_ir.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/w83977af_ir.h	Sun May 30 10:17:03 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Paul VanderSpek
X  * Created at:    Thu Nov 19 13:55:34 1998
- * Modified at:   Thu Dec 10 14:06:18 1998
+ * Modified at:   Mon May  3 12:07:25 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -149,6 +149,29 @@
X #define IRM_CR		0x07 /* Infrared module control register */
X #define IRM_CR_IRX_MSL	0x40
X #define IRM_CR_AF_MNT   0x80 /* Automatic format */
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[10];
+	int head;
+	int tail;
+	int len;
+};
+
+/* Private data for each instance */
+struct w83977af_ir {
+	struct st_fifo st_fifo;
+
+	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
+	int tx_len;          /* Number of frames in tx_buff */
+
+	struct irda_device idev;
+};
X 
X static inline void switch_bank( int iobase, int set)
X {
diff -u --recursive --new-file v2.2.9/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h
--- v2.2.9/linux/include/net/irda/wrapper.h	Wed Mar 10 15:29:50 1999
+++ linux/include/net/irda/wrapper.h	Sun May 30 10:17:03 1999
@@ -1,15 +1,16 @@
X /*********************************************************************
X  *                
X  * Filename:      wrapper.h
- * Version:       1.0
- * Description:   IrDA Wrapper layer
+ * Version:       1.2
+ * Description:   IrDA SIR async wrapper layer
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Jan 29 10:15:46 1999
+ * Modified at:   Mon May  3 09:02:36 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, 
+ *     All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -38,17 +39,18 @@
X #define STA BOF  /* Start flag */
X #define STO EOF  /* End flag */
X 
-#define IR_TRANS 0x20    /* Asynchronous transparency modifier */       
+#define IRDA_TRANS 0x20    /* Asynchronous transparency modifier */       
X 
+/* States for receving a frame in async mode */
X enum {
-	OUTSIDE_FRAME = 1, 
+	OUTSIDE_FRAME, 
X 	BEGIN_FRAME, 
X 	LINK_ESCAPE, 
X 	INSIDE_FRAME
X };
X 
X /* Proto definitions */
-int  async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize);
-void async_unwrap_char( struct irda_device *, __u8 byte);
+int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize);
+inline void async_unwrap_char(struct irda_device *idev, __u8 byte);
X 
X #endif
diff -u --recursive --new-file v2.2.9/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.2.9/linux/include/net/tcp.h	Thu May 13 23:10:31 1999
+++ linux/include/net/tcp.h	Thu Jun  3 08:26:38 1999
@@ -290,7 +290,7 @@
X #define TCP_PROBEWAIT_LEN (1*HZ)/* time to wait between probes when
X 				 * I've got something to write and
X 				 * there is no window			*/
-#define TCP_KEEPALIVE_TIME (180*60*HZ)		/* two hours */
+#define TCP_KEEPALIVE_TIME (120*60*HZ)		/* two hours */
X #define TCP_KEEPALIVE_PROBES	9		/* Max of 9 keepalive probes	*/
X #define TCP_KEEPALIVE_PERIOD ((75*HZ)>>2)	/* period of keepalive check	*/
X 
diff -u --recursive --new-file v2.2.9/linux/include/scsi/scsicam.h linux/include/scsi/scsicam.h
--- v2.2.9/linux/include/scsi/scsicam.h	Thu Jun 12 15:29:27 1997
+++ linux/include/scsi/scsicam.h	Wed Jun  9 16:59:34 1999
@@ -14,4 +14,6 @@
X #define SCSICAM_H
X #include <linux/kdev_t.h>
X extern int scsicam_bios_param (Disk *disk, kdev_t dev, int *ip);
+extern int scsi_partsize(struct buffer_head *bh, unsigned long capacity,
+           unsigned int  *cyls, unsigned int *hds, unsigned int *secs);
X #endif /* def SCSICAM_H */
diff -u --recursive --new-file v2.2.9/linux/include/scsi/sg.h linux/include/scsi/sg.h
--- v2.2.9/linux/include/scsi/sg.h	Tue May 11 13:10:32 1999
+++ linux/include/scsi/sg.h	Mon Jun  7 16:27:06 1999
@@ -12,10 +12,16 @@
X *       Copyright (C) 1998, 1999 Douglas Gilbert
X 
X 
-    Version: 2.1.32 (990501)
-    This version for later 2.1.x series and 2.2.x kernels
+    Version: 2.1.34 (990603)
+    This version for later 2.1.x and 2.2.x series kernels
X     D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au)
X 
+    Changes since 2.1.33 (990521)
+        - implement SG_SET_RESERVED_SIZE and associated memory re-org.
+        - add SG_NEXT_CMD_LEN to override SCSI command lengths
+        - add SG_GET_VERSION_NUM to get version expressed as an integer
+    Changes since 2.1.32 (990501)
+        - fix race condition in sg_read() and sg_open()
X     Changes since 2.1.31 (990327)
X         - add ioctls SG_GET_UNDERRUN_FLAG and _SET_. Change the default
X           to _not_ flag underruns (affects aic7xxx driver)
@@ -25,24 +31,6 @@
X     Changes since 2.1.30 (990320)
X         - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
X         -                increase max allowable mid-level pool usage
-    Changes since 2.1.21 (990315)
-        - skipped to 2.1.30 indicating interface change (revert to 2.1.9)
-        - remove attempt to accomodate cdrecord 1.8, will fix app
-        - keep SG_?ET_RESERVED_SIZE naming for clarity
-    Changes since 2.1.20 (990313)
-        - ommission: left out logic for SG_?ET_ALT_INTERFACE, now added
-    Changes since 2.1.9 (990309)
-        - skipped to version 2.1.20 to indicate some interface changes
-        - incorporate sg changes to make cdrecord 1.8 work (had its
-          own patches that were different from the original)
-        - change SG_?ET_BUFF_SIZE to SG_?ET_RESERVED_SIZE for clarity
-    Changes since 2.1.8 (990303)
-        - debug ">9" option dumps debug for _all_ active sg devices
-        - increase allowable dma pool usage + increase minimum threshhold
-        - pad out sg_scsi_id structure
-    Changes since 2.1.7 (990227)
-        - command queuing now "non-default" [back. compat. with cdparanoia]
-        - Tighten access on some ioctls
X 
X 
X     New features and changes:
@@ -52,24 +40,32 @@
X         - the SCSI target, host and driver status are returned
X           in unused fields of sg_header (maintaining its original size).
X         - asynchronous notification support added (SIGPOLL, SIGIO) for
-          read()s ( write()s should never block).
-        - pack_id logic added so read() can be made to wait for a specific
-          pack_id. 
+          read()s (write()s should never block).
+        - pack_id logic added so read() can wait for a specific pack_id. 
X         - uses memory > ISA_DMA_THRESHOLD if adapter allows it (e.g. a
X           pci scsi adapter).
X         - this driver no longer uses a single SG_BIG_BUFF sized buffer
-          obtained at driver/module init time. Rather it obtains a 
-          SG_SCATTER_SZ buffer when a fd is open()ed and frees it at
-          the corresponding release() (ie pr fd). Hence open() can return
-          ENOMEM! If write() request > SG_SCATTER_SZ bytes for data then
-          it can fail with ENOMEM as well (if so, scale back).
+          obtained at driver/module init time. Rather it tries to obtain a 
+          SG_DEF_RESERVED_SIZE buffer when a fd is open()ed and frees it
+          at the corresponding release() (ie per fd). Actually the "buffer"
+          may be a collection of buffers if scatter-gather is being used.
+        - add SG_SET_RESERVED_SIZE ioctl allowing the user to request a
+          large buffer for duration of current file descriptor's lifetime.
+        - SG_GET_RESERVED_SIZE ioctl can be used to find out how much
+          actually has been reserved.
+        - add SG_NEXT_CMD_LEN ioctl to override SCSI command length on
+          the next write() to this file descriptor.
+        - SG_GET_RESERVED_SIZE's presence as a symbol can be used for
+          compile time identification of the version 2 sg driver.
+          However, it is recommended that run time identification based on
+          calling the ioctl of the same name is a more flexible and
+          safer approach.
X         - adds several ioctl calls, see ioctl section below.
-        - SG_SCATTER_SZ's presence indicates this version of "sg" driver.
X  
X  Good documentation on the original "sg" device interface and usage can be
- found in the Linux HOWTO document: "SCSI Programming HOWTO" by Heiko
- Eissfeldt; last updated 7 May 1996. I will add more info on using the
- extensions in this driver as required. A quick summary:
+ found in the Linux HOWTO document: "SCSI Programming HOWTO" (version 0.5)
+ by Heiko Eissfeldt; last updated 7 May 1996. Here is a quick summary of
+ sg basics:
X  An SG device is accessed by writing SCSI commands plus any associated 
X  outgoing data to it; the resulting status codes and any incoming data
X  are then obtained by a read call. The device can be opened O_NONBLOCK
@@ -88,38 +84,37 @@
X  The given SCSI command has its LUN field overwritten internally by the
X  value associated with the device that has been opened.
X 
- Memory (RAM) is used within this driver for direct memory access (DMA)
- in transferring data to and from the SCSI device. The dreaded ENOMEM
- seems to be more prevalent under early 2.2.x kernels than under the
- 2.0.x kernel series. For a given (large) transfer the memory obtained by
- this driver must be contiguous or scatter-gather must be used (if
- supported by the adapter). [Furthermore, ISA SCSI adapters can only use
- memory below the 16MB level on a i386.]
- This driver tries hard to find some suitable memory before admitting
- defeat and returning ENOMEM. All is not lost if application writers
- then back off the amount they are requesting. The value returned by
- the SG_GET_RESERVED_SIZE ioctl is guaranteed to be available (one
- per fd). This driver does the following:
-   -  attempts to reserve a SG_SCATTER_SZ sized buffer on open(). The
-      actual amount reserved is given by the SG_GET_RESERVED_SIZE ioctl().
-   -  each write() needs to reserve a DMA buffer of the size of the
-      data buffer indicated (excluding sg_header and command overhead).
-      This buffer, depending on its size, adapter type (ISA or not) and
-      the amount of memory available will be obtained from the kernel
-      directly (get_free_pages or kmalloc) or the from the scsi mid-level
-      dma pool (taking care not to exhaust it).
-      If the buffer requested is > SG_SCATTER_SZ or memory is tight then
-      scatter-gather will be used if supported by the adapter.
-  -   write() will also attempt to use the buffer reserved on open()
-      if it is large enough.
- The above strategy ensures that a write() can always depend on a buffer 
- of the size indicated by the SG_GET_RESERVED_SIZE ioctl() (which could be
- 0, but at least the app knows things are tight in advance).
- Hence application writers can adopt quite aggressive strategies (e.g. 
- requesting 512KB) and scale them back in the face of ENOMEM errors.
- N.B. Queuing up commands also ties up kernel memory.
+ This device currently uses "indirect IO" in the sense that data is
+ DMAed into kernel buffers from the hardware and afterwards is
+ transferred into the user space (or vice versa if you are writing).
+ Transfer speeds or up to 20 to 30MBytes/sec have been measured using
+ indirect IO. For faster throughputs "direct IO" which cuts out the
+ double handling of data is required. This will also need a new interface.
+
+ Grabbing memory for those kernel buffers used in this driver for DMA may
+ cause the dreaded ENOMEM error. This error seems to be more prevalent 
+ under early 2.2.x kernels than under the 2.0.x kernel series. For a given 
+ (large) transfer the memory obtained by this driver must be contiguous or
+ scatter-gather must be used (if supported by the adapter). [Furthermore, 
+ ISA SCSI adapters can only use memory below the 16MB level on a i386.]
+
+ When a "sg" device is open()ed O_RDWR then this driver will attempt to
+ reserve a buffer of SG_DEF_RESERVED_SIZE that will be used by subsequent
+ write()s on this file descriptor as long as:
+    -  it is not already in use (eg when command queuing is in use)
+    -  the write() does not call for a buffer size larger than the
+       reserved size.
+ In these cases the write() will attempt to find the memory it needs for
+ DMA buffers dynamically and in the worst case will fail with ENOMEM.
+ The amount of memory actually reserved depends on various dynamic factors
+ and can be checked with the SG_GET_RESERVED_SIZE ioctl(). [In a very
+ tight memory situation it may yield 0!] The size of the reserved buffer
+ can be changed with the SG_SET_RESERVED_SIZE ioctl(). It should be
+ followed with a call to the SG_GET_RESERVED_SIZE ioctl() to find out how
+ much was actually reserved.
X 
- More documentation can be found at www.torque.net/sg
+ More documentation plus test and utility programs can be found at 
+ http://www.torque.net/sg
X */
X 
X #define SG_MAX_SENSE 16   /* too little, unlikely to change in 2.2.x */
@@ -129,7 +124,7 @@
X     int pack_len;    /* [o] reply_len (ie useless), ignored as input */
X     int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
X     int pack_id;     /* [io] id number of packet (use ints >= 0) */
-    int result;      /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */
+    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
X     unsigned int twelve_byte:1; 
X         /* [i] Force 12 byte command length for group 6 & 7 commands  */
X     unsigned int target_status:5;   /* [o] scsi status from target */
@@ -154,9 +149,9 @@
X     int unused3;  
X } Sg_scsi_id;
X 
-/* ioctls  ( _GET_s yield result via 'int *' 3rd argument unless 
-            otherwise indicated */
-#define SG_SET_TIMEOUT 0x2201  /* unit: jiffies, 10ms on i386 */
+/* IOCTLs: ( _GET_s yield result via 'int *' 3rd argument unless 
+             otherwise indicated) */
+#define SG_SET_TIMEOUT 0x2201  /* unit: jiffies (10ms on i386) */
X #define SG_GET_TIMEOUT 0x2202  /* yield timeout as _return_ value */
X 
X #define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */
@@ -165,23 +160,21 @@
X #define SG_SET_TRANSFORM 0x2204
X #define SG_GET_TRANSFORM 0x2205
X 
-#define SG_SET_RESERVED_SIZE 0x2275  /* currently ignored, future addition */
-/* Following yields buffer reserved by open(): 0 <= x <= SG_SCATTER_SZ */
-#define SG_GET_RESERVED_SIZE 0x2272
+#define SG_SET_RESERVED_SIZE 0x2275  /* request a new reserved buffer size */
+#define SG_GET_RESERVED_SIZE 0x2272  /* actual size of reserved buffer */
X 
X /* The following ioctl takes a 'Sg_scsi_id *' object as its 3rd argument. */
-#define SG_GET_SCSI_ID 0x2276   /* Yields fd's bus,chan,dev,lun+type */
+#define SG_GET_SCSI_ID 0x2276   /* Yields fd's bus, chan, dev, lun + type */
X /* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */
X 
-/* Override adapter setting and always DMA using low memory ( <16MB on i386).
-   Default is 0 (off - use adapter setting) */
+/* Override host setting and always DMA using low memory ( <16MB on i386) */
X #define SG_SET_FORCE_LOW_DMA 0x2279  /* 0-> use adapter setting, 1-> force */
X #define SG_GET_LOW_DMA 0x227a   /* 0-> use all ram for dma; 1-> low dma ram */
X 
X /* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which
X    will attempt to read that pack_id or block (or return EAGAIN). If 
X    pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
-   (default) then pack_id ignored by read() and oldest readable fetched. */ 
+   then pack_id ignored by read() and oldest readable fetched. */ 
X #define SG_SET_FORCE_PACK_ID 0x227b
X #define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */
X 
@@ -194,43 +187,47 @@
X /* Yields max scatter gather tablesize allowed by current host adapter */
X #define SG_GET_SG_TABLESIZE 0x227F  /* 0 implies can't do scatter gather */
X 
-/* Control whether sequencing per file descriptor (default) or per device */
-#define SG_GET_MERGE_FD 0x2274   /* 0-> per fd (default), 1-> per device */
+/* Control whether sequencing per file descriptor or per device */
+#define SG_GET_MERGE_FD 0x2274   /* 0-> per fd, 1-> per device */
X #define SG_SET_MERGE_FD 0x2273   /* Attempt to change sequencing state,
-  if more than 1 fd open on device, will fail with EBUSY */
+  if more than current fd open on device, will fail with EBUSY */
X 
X /* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q) */
X #define SG_GET_COMMAND_Q 0x2270   /* Yields 0 (queuing off) or 1 (on) */
X #define SG_SET_COMMAND_Q 0x2271   /* Change queuing state with 0 or 1 */
X 
-/* Get/set whether DMA underrun will cause an error (DID_ERROR) [this only
-   currently applies to the [much-used] aic7xxx driver) */
+/* Get/set whether DMA underrun will cause an error (DID_ERROR). This only
+   currently applies to the [much-used] aic7xxx driver. */
X #define SG_GET_UNDERRUN_FLAG 0x2280 /* Yields 0 (don't flag) or 1 (flag) */
X #define SG_SET_UNDERRUN_FLAG 0x2281 /* Change flag underrun state */
X 
+#define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */
+#define SG_NEXT_CMD_LEN 0x2283  /* override SCSI command length with given
+                   number on the next write() on this file descriptor */
+
+
+#define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
+/* Largest size (in bytes) a single scatter-gather list element can have.
+   The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on 
+   i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
+   by adapter then this value is the largest data block that can be
+   read/written by a single scsi command. The user can find the value of
+   PAGE_SIZE by calling getpagesize() defined in unistd.h . */
X 
X #define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
X #define SG_DEFAULT_RETRIES 1
X 
-/* Default modes, commented if they differ from original sg driver */
+/* Defaults, commented if they differ from original sg driver */
X #define SG_DEF_COMMAND_Q 0
X #define SG_DEF_MERGE_FD 0       /* was 1 -> per device sequencing */
X #define SG_DEF_FORCE_LOW_DMA 0  /* was 1 -> memory below 16MB on i386 */
X #define SG_DEF_FORCE_PACK_ID 0
X #define SG_DEF_UNDERRUN_FLAG 0
+#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ
X 
X /* maximum outstanding requests, write() yields EDOM if exceeded */
X #define SG_MAX_QUEUE 16
X 
-#define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
-/* Largest size (in bytes) a single scatter-gather list element can have.
-   The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on 
-   i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
-   by adapter then this value is the largest data block that can be
-   read/written by a single scsi command. Max number of scatter-gather
-   list elements seems to be limited to 255. */
-
-#define SG_BIG_BUFF SG_SCATTER_SZ       /* for backward compatibility */
-/* #define SG_BIG_BUFF (SG_SCATTER_SZ * 8) */ /* =256KB, if you want */
+#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE    /* for backward compatibility */
X 
X #endif
diff -u --recursive --new-file v2.2.9/linux/kernel/signal.c linux/kernel/signal.c
--- v2.2.9/linux/kernel/signal.c	Tue May 11 13:10:32 1999
+++ linux/kernel/signal.c	Mon Jun  7 16:14:21 1999
@@ -11,6 +11,7 @@
X #include <linux/unistd.h>
X #include <linux/smp_lock.h>
X #include <linux/init.h>
+#include <linux/sched.h>
X 
X #include <asm/uaccess.h>
X 
@@ -324,7 +325,7 @@
X 
X 		if (nr_queued_signals < max_queued_signals) {
X 			q = (struct signal_queue *)
-			    kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
+			    kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
X 		}
X 		
X 		if (q) {
@@ -417,6 +418,7 @@
X 	if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN)
X 		t->sig->action[sig-1].sa.sa_handler = SIG_DFL;
X 	sigdelset(&t->blocked, sig);
+	recalc_sigpending(t);
X 	spin_unlock_irqrestore(&t->sigmask_lock, flags);
X 
X 	return send_sig_info(sig, info, t);
diff -u --recursive --new-file v2.2.9/linux/kernel/sys.c linux/kernel/sys.c
--- v2.2.9/linux/kernel/sys.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/sys.c	Mon Jun  7 16:18:16 1999
@@ -900,6 +900,8 @@
X 		return -EINVAL;
X 	if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
X 		return -EFAULT;
+	if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
+		return -EINVAL;
X 	old_rlim = current->rlim + resource;
X 	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
X 	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
diff -u --recursive --new-file v2.2.9/linux/mm/memory.c linux/mm/memory.c
--- v2.2.9/linux/mm/memory.c	Fri Apr 16 14:47:31 1999
+++ linux/mm/memory.c	Tue Jun  8 12:47:16 1999
@@ -622,7 +622,7 @@
X 	
X 	pte = *page_table;
X 	new_page = __get_free_page(GFP_USER);
-	/* Did someone else copy this page for us while we slept? */
+	/* Did swap_out() unmapped the protected page while we slept? */
X 	if (pte_val(*page_table) != pte_val(pte))
X 		goto end_wp_page;
X 	if (!pte_present(pte))
@@ -652,36 +652,42 @@
X 		delete_from_swap_cache(page_map);
X 		/* FallThrough */
X 	case 1:
-		/* We can release the kernel lock now.. */
-		unlock_kernel();
-
X 		flush_cache_page(vma, address);
X 		set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
X 		flush_tlb_page(vma, address);
X end_wp_page:
+		/*
+		 * We can release the kernel lock now.. Now swap_out will see
+		 * a dirty page and so won't get confused and flush_tlb_page
+		 * won't SMP race. -Andrea
+		 */
+		unlock_kernel();
+
X 		if (new_page)
X 			free_page(new_page);
X 		return 1;
X 	}
X 		
-	unlock_kernel();
X 	if (!new_page)
-		return 0;
+		goto no_new_page;
X 
-	if (PageReserved(mem_map + MAP_NR(old_page)))
+	if (PageReserved(page_map))
X 		++vma->vm_mm->rss;
X 	copy_cow_page(old_page,new_page);
X 	flush_page_to_ram(old_page);
X 	flush_page_to_ram(new_page);
X 	flush_cache_page(vma, address);
X 	set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
-	free_page(old_page);
X 	flush_tlb_page(vma, address);
+	unlock_kernel();
+	__free_page(page_map);
X 	return 1;
X 
X bad_wp_page:
X 	printk("do_wp_page: bogus page at address %08lx (%08lx)\n",address,old_page);
X 	send_sig(SIGKILL, tsk, 1);
+no_new_page:
+	unlock_kernel();
X 	if (new_page)
X 		free_page(new_page);
X 	return 0;
diff -u --recursive --new-file v2.2.9/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.2.9/linux/mm/swapfile.c	Wed Mar 10 15:29:50 1999
+++ linux/mm/swapfile.c	Mon Jun  7 16:27:06 1999
@@ -5,6 +5,7 @@
X  *  Swap reorganised 29.12.95, Stephen Tweedie
X  */
X 
+#include <linux/config.h>
X #include <linux/malloc.h>
X #include <linux/smp_lock.h>
X #include <linux/kernel_stat.h>
@@ -554,7 +555,7 @@
X 	} else if (S_ISREG(swap_dentry->d_inode->i_mode)) {
X 		error = -EBUSY;
X 		for (i = 0 ; i < nr_swapfiles ; i++) {
-			if (i == type)
+			if (i == type || !swap_info[i].swap_file)
X 				continue;
X 			if (swap_dentry->d_inode == swap_info[i].swap_file->d_inode)
X 				goto bad_swap;
diff -u --recursive --new-file v2.2.9/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.2.9/linux/net/core/datagram.c	Mon Oct  5 13:13:47 1998
+++ linux/net/core/datagram.c	Wed Jun  2 11:29:28 1999
@@ -6,7 +6,7 @@
X  *	This is used because UDP, RAW, PACKET, DDP, IPX, AX.25 and NetROM layer all have identical poll code and mostly
X  *	identical recvmsg() code. So we share it here. The poll was shared before but buried in udp.c so I moved it.
X  *
- *	Authors:	Alan Cox <al...@cymru.net>. (datagram_poll() from old udp.c code)
+ *	Authors:	Alan Cox <al...@redhat.com>. (datagram_poll() from old udp.c code)
X  *
X  *	Fixes:
X  *		Alan Cox	:	NULL return from skb_peek_copy() understood
diff -u --recursive --new-file v2.2.9/linux/net/core/filter.c linux/net/core/filter.c
--- v2.2.9/linux/net/core/filter.c	Mon Mar 29 11:09:12 1999
+++ linux/net/core/filter.c	Sat May 15 17:43:52 1999
@@ -106,7 +106,7 @@
X 				continue;
X 
X 			case BPF_ALU|BPF_MUL|BPF_K:
-				A *= X;
+				A *= fentry->k;
X 				continue;
X 
X 			case BPF_ALU|BPF_DIV|BPF_X:
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.2.9/linux/net/ipv4/af_inet.c	Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/af_inet.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		PF_INET protocol family socket handler.
X  *
- * Version:	$Id: af_inet.c,v 1.87 1999/04/22 10:07:33 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.87.2.1 1999/05/29 04:32:01 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -147,14 +147,8 @@
X 	struct sk_buff *skb;
X 
X 	/* First the read buffer. */
-	while((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
-		/* This will take care of closing sockets that were
-		 * listening and didn't accept everything.
-		 */
-		if (skb->sk != NULL && skb->sk != sk)
-			skb->sk->prot->close(skb->sk, 0);
+	while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
X 		kfree_skb(skb);
-	}
X 
X 	/* Next, the error queue. */
X 	while((skb = skb_dequeue(&sk->error_queue)) != NULL)
@@ -213,12 +207,6 @@
X 
X 	kill_sk_queues(sk);
X 
-	/* Now if it has a half accepted/ closed socket. */
-	if (sk->pair) {
-		sk->pair->prot->close(sk->pair, 0);
-		sk->pair = NULL;
-  	}
-
X 	/* Now if everything is gone we can free the socket
X 	 * structure, otherwise we need to keep it around until
X 	 * everything is gone.
@@ -684,14 +672,8 @@
X 	if (sk1->prot->accept == NULL)
X 		goto do_err;
X 
-	/* Restore the state if we have been interrupted, and then returned. */
-	if (sk1->pair != NULL) {
-		sk2 = sk1->pair;
-		sk1->pair = NULL;
-	} else {
-		if((sk2 = sk1->prot->accept(sk1,flags)) == NULL)
-			goto do_sk1_err;
-	}
+	if((sk2 = sk1->prot->accept(sk1,flags)) == NULL)
+		goto do_sk1_err;
X 
X 	/*
X 	 *	We've been passed an extra socket.
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.2.9/linux/net/ipv4/icmp.c	Tue Mar 23 14:35:48 1999
+++ linux/net/ipv4/icmp.c	Tue Jun  8 20:33:07 1999
@@ -1,9 +1,9 @@
X /*
X  *	NET3:	Implementation of the ICMP protocol layer. 
X  *	
- *		Alan Cox, <al...@cymru.net>
+ *		Alan Cox, <al...@redhat.com>
X  *
- *	Version: $Id: icmp.c,v 1.52 1999/03/21 12:04:11 davem Exp $
+ *	Version: $Id: icmp.c,v 1.52.2.1 1999/06/09 01:56:07 davem Exp $
X  *
X  *	This program is free software; you can redistribute it and/or
X  *	modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.2.9/linux/net/ipv4/ip_fw.c	Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/ip_fw.c	Tue Jun  8 20:33:07 1999
@@ -34,6 +34,9 @@
X  *              Marc Santoro <ult...@snicker.emoti.com>
X  * 29-Jan-1999: Locally generated bogus IPs dealt with, rather than crash
X  *              during dump_packet. --RR.
+ * 19-May-1999: Star Wars: The Phantom Menace opened.  Rule num
+ *		printed in log (modified from Michael Hasenstein's patch).
+ *		Added SYN in log message. --RR
X  */
X 
X /*
@@ -400,7 +403,9 @@
X 			struct ip_fwkernel *f, 
X 			const ip_chainlabel chainlabel,
X 			__u16 src_port, 
-			__u16 dst_port)
+			__u16 dst_port,
+			unsigned int count,
+			int syn)
X {
X 	__u32 *opt = (__u32 *) (ip + 1);
X 	int opti;
@@ -432,7 +437,7 @@
X 
X 	for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
X 		printk(" O=0x%8.8X", *opt++);
-	printk("\n");
+	printk(" %s(#%d)\n", syn ? "SYN " : /* "PENANCE" */ "", count);
X }
X 
X /* function for checking chain labels for user space. */
@@ -520,12 +525,14 @@
X 	      const ip_chainlabel label,
X 	      struct sk_buff *skb,
X 	      unsigned int slot,
-	      __u16 src_port, __u16 dst_port)
+	      __u16 src_port, __u16 dst_port, 
+	      unsigned int count,
+	      int tcpsyn)
X {
X 	f->counters[slot].bcnt+=ntohs(ip->tot_len);
X 	f->counters[slot].pcnt++;
X 	if (f->ipfw.fw_flg & IP_FW_F_PRN) {
-		dump_packet(ip,rif,f,label,src_port,dst_port);
+		dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn);
X 	}
X 	ip->tos = (ip->tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor;
X 
@@ -590,6 +597,7 @@
X 	unsigned char		oldtos;
X 	struct ip_fwkernel	*f;	
X 	int			ret = FW_SKIP+2;
+	unsigned int		count;
X 
X 	/* We handle fragments by dealing with the first fragment as
X 	 * if it was a normal packet.  All other fragments are treated
@@ -610,7 +618,7 @@
X 	if (offset == 1 && ip->protocol == IPPROTO_TCP)	{
X 		if (!testing && net_ratelimit()) {
X 			printk("Suspect TCP fragment.\n");
-			dump_packet(ip,rif,NULL,NULL,0,0);
+			dump_packet(ip,rif,NULL,NULL,0,0,0,0);
X 		}
X 		return FW_BLOCK;
X 	}
@@ -702,13 +710,16 @@
X 
X 	f = chain->chain;
X 	do {
+		count = 0;
X 		for (; f; f = f->next) {
+			count++;
X 			if (ip_rule_match(f,rif,ip,
X 					  tcpsyn,src_port,dst_port,offset)) {
X 				if (!testing
X 				    && !ip_fw_domatch(f, ip, rif, chain->label,
X 						      skb, slot, 
-						      src_port, dst_port)) {
+						      src_port, dst_port,
+						      count, tcpsyn)) {
X 					ret = FW_BLOCK;
X 					goto out;
X 				}
@@ -1408,8 +1419,10 @@
X 		else if ((chain = find_label(new->fwc_label)) == NULL)
X 			ret = ENOENT;
X 		else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret))
-			 != NULL)
+			 != NULL) {
X 			ret = del_rule_from_chain(chain, ip_fwkern);
+			kfree(ip_fwkern);
+		}
X 	}
X 	break;
X 
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/ip_options.c linux/net/ipv4/ip_options.c
--- v2.2.9/linux/net/ipv4/ip_options.c	Tue Mar 23 14:35:48 1999
+++ linux/net/ipv4/ip_options.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		The options processing module for ip.c
X  *
- * Version:	$Id: ip_options.c,v 1.16 1999/03/21 05:22:40 davem Exp $
+ * Version:	$Id: ip_options.c,v 1.16.2.1 1999/06/02 04:06:19 davem Exp $
X  *
X  * Authors:	A.N.Kuznetsov
X  *		
@@ -452,7 +452,6 @@
X error:
X 	if (skb) {
X 		icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
-		kfree_skb(skb);
X 	}
X 	return -EINVAL;
X }
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.2.9/linux/net/ipv4/ipmr.c	Mon Mar 29 11:09:12 1999
+++ linux/net/ipv4/ipmr.c	Tue Jun  8 20:33:07 1999
@@ -1,7 +1,7 @@
X /*
X  *	IP multicast routing support for mrouted 3.6/3.8
X  *
- *		(c) 1995 Alan Cox, <al...@cymru.net>
+ *		(c) 1995 Alan Cox, <al...@redhat.com>
X  *	  Linux Consultancy and Custom Driver Development
X  *
X  *	This program is free software; you can redistribute it and/or
@@ -9,7 +9,7 @@
X  *	as published by the Free Software Foundation; either version
X  *	2 of the License, or (at your option) any later version.
X  *
- *	Version: $Id: ipmr.c,v 1.40 1999/03/25 10:04:25 davem Exp $
+ *	Version: $Id: ipmr.c,v 1.40.2.1 1999/06/09 01:56:17 davem Exp $
X  *
X  *	Fixes:
X  *	Michael Chastain	:	Incorrect size of copying.
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.2.9/linux/net/ipv4/tcp.c	Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/tcp.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp.c,v 1.140 1999/04/22 10:34:31 davem Exp $
+ * Version:	$Id: tcp.c,v 1.140.2.1 1999/05/29 04:16:48 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -896,6 +896,7 @@
X 					err = -ERESTARTSYS;
X 					goto do_interrupted;
X 				}
+				tcp_push_pending_frames(sk, tp);
X 				wait_for_tcp_memory(sk);
X 
X 				/* If SACK's were formed or PMTU events happened,
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.2.9/linux/net/ipv4/tcp_input.c	Tue May 11 13:10:32 1999
+++ linux/net/ipv4/tcp_input.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_input.c,v 1.164 1999/05/08 21:09:52 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.3 1999/06/02 04:15:06 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -748,7 +748,6 @@
X static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
X {
X 	struct sk_buff *skb = skb_peek(&sk->write_queue);
-	__u32 when = tp->rto - (tcp_time_stamp - TCP_SKB_CB(skb)->when);
X 
X 	/* Some data was ACK'd, if still retransmitting (due to a
X 	 * timeout), resend more of the retransmit queue.  The
@@ -758,6 +757,9 @@
X 		tcp_xmit_retransmit_queue(sk);
X 		tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
X 	} else {
+		__u32 when = tp->rto - (tcp_time_stamp - TCP_SKB_CB(skb)->when);
+		if ((__s32)when < 0)
+			when = 1;
X 		tcp_reset_xmit_timer(sk, TIME_RETRANS, when);
X 	}
X }
@@ -785,8 +787,6 @@
X 	if (after(ack, tp->snd_nxt) || before(ack, tp->snd_una))
X 		goto uninteresting_ack;
X 
-	dst_confirm(sk->dst_cache);
-
X 	/* If there is data set flag 1 */
X 	if (len != th->doff*4) {
X 		flag |= FLAG_DATA;
@@ -882,6 +882,24 @@
X 		/* Clear any aborted fast retransmit starts. */
X 		tp->dup_acks = 0;
X 	}
+	/* It is not a brain fart, I thought a bit now. 8)
+	 *
+	 * Forward progress is indicated, if:
+	 *   1. the ack acknowledges new data.
+	 *   2. or the ack is duplicate, but it is caused by new segment
+	 *      arrival. This case is filtered by:
+	 *      - it contains no data, syn or fin.
+	 *      - it does not update window.
+	 *   3. or new SACK. It is difficult to check, so that we ignore it.
+	 *
+	 * Forward progress is also indicated by arrival new data,
+	 * which was caused by window open from our side. This case is more
+	 * difficult and it is made (alas, incorrectly) in tcp_data_queue().
+	 *                                              --ANK (990513)
+	 */
+	if (ack != tp->snd_una || (flag == 0 && !th->fin))
+		dst_confirm(sk->dst_cache);
+
X 	/* Remember the highest ack received. */
X 	tp->snd_una = ack;
X 	return 1;
@@ -1801,7 +1819,7 @@
X 		}
X 	}
X 
-	flg = *(((u32 *)th) + 3) & ~htonl(0x8 << 16);
+	flg = *(((u32 *)th) + 3) & ~htonl(0xFC8 << 16);
X 
X 	/*	pred_flags is 0xS?10 << 16 + snd_wnd
X 	 *	if header_predition is to be made
@@ -2067,21 +2085,81 @@
X 		 * not be in line code. [AC]
X 		 */
X 		if(th->ack) {
-			tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
-
-			/* We got an ack, but it's not a good ack. */
-			if(!tcp_ack(sk,th, TCP_SKB_CB(skb)->seq,
-				    TCP_SKB_CB(skb)->ack_seq, len)) 
+			/* rfc793:
+			 * "If the state is SYN-SENT then
+			 *    first check the ACK bit
+			 *      If the ACK bit is set
+			 *	  If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send
+			 *        a reset (unless the RST bit is set, if so drop
+			 *        the segment and return)"
+			 *
+			 *  I cite this place to emphasize one essential
+			 *  detail, this check is different of one
+			 *  in established state: SND.UNA <= SEG.ACK <= SND.NXT.
+			 *  SEG_ACK == SND.UNA == ISS is invalid in SYN-SENT,
+			 *  because we have no previous data sent before SYN.
+			 *                                        --ANK(990513)
+			 *
+			 *  We do not send data with SYN, so that RFC-correct
+			 *  test reduces to:
+			 */
+			if (sk->zapped ||
+			    TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt)
X 				return 1;
X 
-			if(th->rst) {
+			/* Now ACK is acceptable.
+			 *
+			 * "If the RST bit is set
+			 *    If the ACK was acceptable then signal the user "error:
+			 *    connection reset", drop the segment, enter CLOSED state,
+			 *    delete TCB, and return."
+			 */
+
+			if (th->rst) {
X 				tcp_reset(sk);
X 				goto discard;
X 			}
X 
-			if(!th->syn) 
+			/* rfc793:
+			 *   "fifth, if neither of the SYN or RST bits is set then
+			 *    drop the segment and return."
+			 *
+			 *    See note below!
+			 *                                        --ANK(990513)
+		         */
+			
+			if (!th->syn)
X 				goto discard;
X 
+			/* rfc793:
+			 *   "If the SYN bit is on ...
+			 *    are acceptable then ...
+			 *    (our SYN has been ACKed), change the connection
+			 *    state to ESTABLISHED..."
+			 *
+			 * Do you see? SYN-less ACKs in SYN-SENT state are
+			 * completely ignored.
+			 *
+			 * The bug causing stalled SYN-SENT sockets
+			 * was here: tcp_ack advanced snd_una and canceled
+			 * retransmit timer, so that bare ACK received
+			 * in SYN-SENT state (even with invalid ack==ISS,
+			 * because tcp_ack check is too weak for SYN-SENT)
+			 * causes moving socket to invalid semi-SYN-SENT,
+			 * semi-ESTABLISHED state and connection hangs.
+			 *
+			 * There exist buggy stacks, which really send
+			 * such ACKs: f.e. 202.226.91.94 (okigate.oki.co.jp)
+			 * Actually, if this host did not try to get something
+			 * from ftp.inr.ac.ru I'd never find this bug 8)
+			 *
+			 *                                     --ANK (990514)
+			 */
+
+			tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+			tcp_ack(sk,th, TCP_SKB_CB(skb)->seq,
+				TCP_SKB_CB(skb)->ack_seq, len);
+
X 			/* Ok.. it's good. Set up sequence numbers and
X 			 * move to established.
X 			 */
@@ -2206,8 +2284,8 @@
X 	    !(th->fin && TCP_SKB_CB(skb)->end_seq == tp->rcv_nxt)) {
X 		if (!th->rst) {
X 			tcp_send_ack(sk);
-			goto discard;
X 		}
+		goto discard;
X 	}
X 
X 	/* step 2: check RST bit */
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.2.9/linux/net/ipv4/tcp_ipv4.c	Tue May 11 13:10:32 1999
+++ linux/net/ipv4/tcp_ipv4.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_ipv4.c,v 1.175 1999/05/08 21:09:54 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.175.2.2 1999/06/02 04:06:15 davem Exp $
X  *
X  *		IPv4 specific functions
X  *
@@ -1328,7 +1328,6 @@
X 
X 		newsk->done = 0;
X 		newsk->proc = 0;
-		newsk->pair = NULL;
X 		skb_queue_head_init(&newsk->back_log);
X 		skb_queue_head_init(&newsk->error_queue);
X #ifdef CONFIG_FILTER
@@ -1648,6 +1647,7 @@
X 	/* Count it even if it's bad */
X 	tcp_statistics.TcpInSegs++;
X 
+	len = skb->len;
X 	if (len < sizeof(struct tcphdr))
X 		goto bad_packet;
X 
@@ -1673,6 +1673,10 @@
X 	default:
X 		/* CHECKSUM_UNNECESSARY */
X 	}
+
+	if((th->doff * 4) < sizeof(struct tcphdr) ||
+	   len < (th->doff * 4))
+		goto bad_packet;
X 
X #ifdef CONFIG_IP_TRANSPARENT_PROXY
X 	if (IPCB(skb)->redirport)
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.2.9/linux/net/ipv4/tcp_output.c	Tue May 11 13:10:32 1999
+++ linux/net/ipv4/tcp_output.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_output.c,v 1.108 1999/05/08 21:48:59 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.108.2.1 1999/05/14 23:07:36 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -239,6 +239,11 @@
X 
X 	/* Rechecksum original buffer. */
X 	skb->csum = csum_partial(skb->data, skb->len, 0);
+
+	/* Looks stupid, but our code really uses when of
+	 * skbs, which it never sent before. --ANK
+	 */
+	TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
X 
X 	/* Link BUFF into the send queue. */
X 	__skb_append(skb, buff);
diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.2.9/linux/net/ipv4/tcp_timer.c	Tue May 11 13:10:32 1999
+++ linux/net/ipv4/tcp_timer.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_timer.c,v 1.62 1999/05/08 21:09:55 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.62.2.2 1999/06/02 04:06:21 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -537,14 +537,11 @@
X 					conn = req;
X 					req = req->dl_next;
X 
-					if (conn->sk) {
+					if (conn->sk ||
+					    ((long)(now - conn->expires)) <= 0) {
X 						prev = conn; 
X 						continue; 
X 					}
-
-					if ((long)(now - conn->expires) <= 0)
-						break;
-
X 
X 					tcp_synq_unlink(tp, conn, prev);
X 					if (conn->retrans >= sysctl_tcp_retries1) {
diff -u --recursive --new-file v2.2.9/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- v2.2.9/linux/net/ipv6/icmp.c	Tue Mar 23 14:35:48 1999
+++ linux/net/ipv6/icmp.c	Sat May 29 11:10:33 1999
@@ -5,7 +5,7 @@
X  *	Authors:
X  *	Pedro Roque		<ro...@di.fc.ul.pt>
X  *
- *	$Id: icmp.c,v 1.21 1999/03/21 05:22:51 davem Exp $
+ *	$Id: icmp.c,v 1.21.2.1 1999/05/19 22:07:36 davem Exp $
X  *
X  *	Based on net/ipv4/icmp.c
X  *
@@ -315,6 +315,7 @@
X 	fl.nl_u.ip6_u.daddr = &hdr->saddr;
X 	fl.nl_u.ip6_u.saddr = saddr;
X 	fl.oif = iif;
+	fl.fl6_flowlabel = 0;
X 	fl.uli_u.icmpt.type = type;
X 	fl.uli_u.icmpt.code = code;
X 
@@ -388,6 +389,7 @@
X 	fl.nl_u.ip6_u.daddr = &hdr->saddr;
X 	fl.nl_u.ip6_u.saddr = saddr;
X 	fl.oif = skb->dev->ifindex;
+	fl.fl6_flowlabel = 0;
X 	fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
X 	fl.uli_u.icmpt.code = 0;
X 
diff -u --recursive --new-file v2.2.9/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.2.9/linux/net/ipv6/tcp_ipv6.c	Wed Apr 28 11:37:32 1999
+++ linux/net/ipv6/tcp_ipv6.c	Wed Jun  2 09:55:22 1999
@@ -5,7 +5,7 @@
X  *	Authors:
X  *	Pedro Roque		<ro...@di.fc.ul.pt>	
X  *
- *	$Id: tcp_ipv6.c,v 1.104 1999/04/24 00:27:25 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.104.2.2 1999/06/02 04:06:27 davem Exp $
X  *
X  *	Based on: 
X  *	linux/net/ipv4/tcp.c
@@ -551,7 +551,7 @@
X 
X failure:
X 	dst_release(xchg(&sk->dst_cache, NULL));
-	memcpy(&np->daddr, 0, sizeof(struct in6_addr));
+	memset(&np->daddr, 0, sizeof(struct in6_addr));
X 	sk->daddr = 0;
X 	return err;
X }
@@ -1362,6 +1362,7 @@
X 
X 	tcp_statistics.TcpInSegs++;
X 
+	len = skb->len;
X 	if (len < sizeof(struct tcphdr))
X 		goto bad_packet;
X 
@@ -1382,6 +1383,10 @@
X 	default:
X 		/* CHECKSUM_UNNECESSARY */
X 	};
+
+	if((th->doff * 4) < sizeof(struct tcphdr) ||
+	   len < (th->doff * 4))
+		goto bad_packet;
X 
X 	sk = __tcp_v6_lookup(th, saddr, th->source, daddr, th->dest, tcp_v6_iif(skb));
X 
diff -u --recursive --new-file v2.2.9/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.2.9/linux/net/irda/Config.in	Fri Apr 16 14:47:31 1999
+++ linux/net/irda/Config.in	Mon Jun  7 16:19:59 1999
@@ -2,34 +2,31 @@
X # IrDA protocol configuration
X #
X 
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  if [ "$CONFIG_NET" != "n" ] ; then
+if [ "$CONFIG_NET" != "n" ] ; then
X 
-    mainmenu_option next_comment
-    comment 'IrDA subsystem support'
-    dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_EXPERIMENTAL $CONFIG_NET
+  mainmenu_option next_comment
+  comment 'IrDA subsystem support'
+  dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
X 
-    if [ "$CONFIG_IRDA" != "n" ] ; then
-      comment 'IrDA protocols'
-      source net/irda/irlan/Config.in
-      source net/irda/ircomm/Config.in
-      source net/irda/irlpt/Config.in
+  if [ "$CONFIG_IRDA" != "n" ] ; then
+    comment 'IrDA protocols'
+    source net/irda/irlan/Config.in
+    source net/irda/ircomm/Config.in
+    source net/irda/irlpt/Config.in
X 
-      bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
-      if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
-        comment '   IrDA options'
-        bool '   Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
-	bool '   Fast RRs' CONFIG_IRDA_FAST_RR
-	bool '   Debug information' CONFIG_IRDA_DEBUG
-      fi
+    bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
+    if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
+      comment '   IrDA options'
+      bool '   Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
+      bool '   Fast RRs' CONFIG_IRDA_FAST_RR
+      bool '   Debug information' CONFIG_IRDA_DEBUG
X     fi
+  fi
X 
-    if [ "$CONFIG_IRDA" != "n" ] ; then
-      source net/irda/compressors/Config.in
-      source drivers/net/irda/Config.in
-    fi
-  endmenu
-
+  if [ "$CONFIG_IRDA" != "n" ] ; then
+    source net/irda/compressors/Config.in
+    source drivers/net/irda/Config.in
X   fi
+  endmenu
X fi
X 
diff -u --recursive --new-file v2.2.9/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.2.9/linux/net/irda/af_irda.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/af_irda.c	Mon Jun  7 16:19:59 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Thu Apr 22 12:08:04 1999
+ * Modified at:   Wed May 19 16:12:06 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
X  * 
@@ -30,6 +30,7 @@
X #include <linux/if_arp.h>
X #include <linux/net.h>
X #include <linux/irda.h>
+#include <linux/poll.h>
X 
X #include <asm/uaccess.h>
X 
@@ -46,11 +47,12 @@
X extern int  irlap_driver_rcv(struct sk_buff *, struct device *, 
X 			     struct packet_type *);
X 
-static struct proto_ops irda_proto_ops;
+static struct proto_ops irda_stream_ops;
+static struct proto_ops irda_dgram_ops;
X static hashbin_t *cachelog = NULL;
X static struct wait_queue *discovery_wait; /* Wait for discovery */
X 
-#define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+#define IRDA_MAX_HEADER (TTP_MAX_HEADER)
X 
X /*
X  * Function irda_data_indication (instance, sap, skb)
@@ -121,7 +123,8 @@
X  */
X static void irda_connect_confirm(void *instance, void *sap, 
X 				 struct qos_info *qos,
-				 __u32 max_sdu_size, struct sk_buff *skb)
+				 __u32 max_sdu_size, __u8 max_header_size, 
+				 struct sk_buff *skb)
X {
X 	struct irda_sock *self;
X 	struct sock *sk;
@@ -130,13 +133,28 @@
X 
X 	self = (struct irda_sock *) instance;
X 
+	/* How much header space do we need to reserve */
+	self->max_header_size = max_header_size;
+
+	/* IrTTP max SDU size in transmit direction */
X 	self->max_sdu_size_tx = max_sdu_size;
+
+	/* Find out what the largest chunk of data that we can transmit is */
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_data_size = qos->data_size.value - max_header_size;
+	else
+		self->max_data_size = max_sdu_size;
+
+	DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+
X 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
X 
X 	sk = self->sk;
X 	if (sk == NULL)
X 		return;
X 
+	skb_queue_tail(&sk->receive_queue, skb);
+
X 	/* We are now connected! */
X 	sk->state = TCP_ESTABLISHED;
X 	sk->state_change(sk);
@@ -150,7 +168,7 @@
X  */
X static void irda_connect_indication(void *instance, void *sap, 
X 				    struct qos_info *qos, __u32 max_sdu_size,
-				    struct sk_buff *skb)
+				    __u8 max_header_size, struct sk_buff *skb)
X {
X 	struct irda_sock *self;
X 	struct sock *sk;
@@ -158,8 +176,21 @@
X 	DEBUG(1, __FUNCTION__ "()\n");
X 
X 	self = (struct irda_sock *) instance;
-	
-	self->max_sdu_size_tx = max_sdu_size;
+
+	/* How much header space do we need to reserve */
+	self->max_header_size = max_header_size;
+
+	/* IrTTP max SDU size in transmit direction */
+	self->max_sdu_size_tx = max_sdu_size;	
+
+	/* Find out what the largest chunk of data that we can transmit is */
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_data_size = qos->data_size.value - max_header_size;
+	else
+		self->max_data_size = max_sdu_size;
+
+	DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+
X 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
X 
X 	sk = self->sk;
@@ -187,12 +218,12 @@
X 
X 	skb = dev_alloc_skb(64);
X 	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n");
+		DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n");
X 		return;
X 	}
X 
X 	/* Reserve space for MUX_CONTROL and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER);
+	skb_reserve(skb, IRDA_MAX_HEADER);
X 
X 	irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);
X }
@@ -219,12 +250,12 @@
X 	
X 	switch (flow) {
X 	case FLOW_STOP:
-		DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n");
+		DEBUG(1, __FUNCTION__ "(), IrTTP wants us to slow down\n");
X 		self->tx_flow = flow;
X 		break;
X 	case FLOW_START:
X 		self->tx_flow = flow;
-		DEBUG(0, __FUNCTION__ "(), IrTTP wants us to start again\n");
+		DEBUG(1, __FUNCTION__ "(), IrTTP wants us to start again\n");
X 		wake_up_interruptible(sk->sleep);
X 		break;
X 	default:
@@ -514,10 +545,13 @@
X 	new->stsap_sel = new->tsap->stsap_sel;
X 	new->dtsap_sel = new->tsap->dtsap_sel;
X 	new->saddr = irttp_get_saddr(new->tsap);
-	new->saddr = irttp_get_saddr(new->tsap);
+	new->daddr = irttp_get_daddr(new->tsap);
X 
X 	new->max_sdu_size_tx = self->max_sdu_size_tx;
X 	new->max_sdu_size_rx = self->max_sdu_size_rx;
+	new->max_data_size   = self->max_data_size;
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 18'
echo 'File patch-2.2.10 is continued in part 19'
echo 19 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 22 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 22; 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
X 
-		len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ",
-				lap->saddr, lap->daddr); 
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
+			       lap->saddr, lap->daddr); 
+		len += sprintf(buf+len, "\n");
X 
X 		len += sprintf( buf+len, "\nConnected LSAPs:\n");
X 		self = (struct lsap_cb *) hashbin_get_first( lap->lsaps);
-		while ( self != NULL) {
-			ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;);
-			len += sprintf( buf+len, "lsap state: %s, ", 
-					irlsap_state[ self->lsap_state]);
-			len += sprintf( buf+len, 
-					"slsap_sel: %#02x, dlsap_sel: %#02x, ",
-					self->slsap_sel, self->dlsap_sel);
-			len += sprintf( buf+len, "(%s)", self->notify.name);
-			len += sprintf( buf+len, "\n");
+		while (self != NULL) {
+			ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
+			len += sprintf(buf+len, "lsap state: %s, ", 
+				       irlsap_state[ self->lsap_state]);
+			len += sprintf(buf+len, 
+				       "slsap_sel: %#02x, dlsap_sel: %#02x, ",
+				       self->slsap_sel, self->dlsap_sel);
+			len += sprintf(buf+len, "(%s)", self->notify.name);
+			len += sprintf(buf+len, "\n");
X 			
-			self = ( struct lsap_cb *) hashbin_get_next( 
+			self = (struct lsap_cb *) hashbin_get_next( 
X 				lap->lsaps);
X 		} 
+		len += sprintf(buf+len, "\n");
X 
-		lap = ( struct lap_cb *) hashbin_get_next( 
-			irlmp->links);
+		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
X  	} 
X 
X 	restore_flags( flags);
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.2.9/linux/net/irda/irlmp_frame.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irlmp_frame.c	Mon Jun  7 16:19:59 1999
@@ -1,15 +1,15 @@
X /*********************************************************************
X  *                
X  * Filename:      irlmp_frame.c
- * Version:       0.8
+ * Version:       0.9
X  * Description:   IrLMP frame implementation
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Fri Apr 23 09:12:23 1999
+ * Modified at:   Mon May 31 09:53:16 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>
X * All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
@@ -59,16 +59,16 @@
X  *
X  *    Send Link Control Frame to IrLAP
X  */
-void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap,
-			 __u8 opcode, struct sk_buff *skb) 
+void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+			__u8 opcode, struct sk_buff *skb) 
X {
X 	__u8 *frame;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
X 	
X 	frame = skb->data;
X 	
@@ -82,8 +82,8 @@
X 	else
X 		frame[3] = 0x00; /* rsvd */
X 
-	ASSERT( self->irlap != NULL, return;);
-	irlap_data_request( self->irlap, skb, TRUE);
+	ASSERT(self->irlap != NULL, return;);
+	irlap_data_request(self->irlap, skb, TRUE);
X }
X 
X /*
@@ -112,7 +112,7 @@
X 	 */
X 	slsap_sel = fp[0] & LSAP_MASK; 
X 	dlsap_sel = fp[1];
-	
+
X 	/*
X 	 *  Check if this is an incoming connection, since we must deal with
X 	 *  it in a different way than other established connections.
@@ -134,17 +134,17 @@
X 				       self->lsaps);
X 	
X 	if (lsap == NULL) {
-		DEBUG(0, "IrLMP, Sorry, no LSAP for received frame!\n");
-		DEBUG(0, __FUNCTION__ 
+		DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
+		DEBUG(2, __FUNCTION__ 
X 		      "(), slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, 
X 		      dlsap_sel);
X 		if (fp[0] & CONTROL_BIT) {
-			DEBUG(0, __FUNCTION__ 
+			DEBUG(2, __FUNCTION__ 
X 			      "(), received control frame %02x\n", fp[2]);
X 		} else {
-			DEBUG(0, __FUNCTION__ "(), received data frame\n");
+			DEBUG(2, __FUNCTION__ "(), received data frame\n");
X 		}
-		dev_kfree_skb( skb);
+		dev_kfree_skb(skb);
X 		return;
X 	}
X 
@@ -224,11 +224,11 @@
X  *    Incoming LAP connection!
X  *
X  */
-void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, 
-				    __u32 daddr, struct qos_info *qos,
-				    struct sk_buff *skb) 
+void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr, 
+				   __u32 daddr, struct qos_info *qos,
+				   struct sk_buff *skb) 
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
X 	/* Copy QoS settings for this session */
X 	self->qos = qos;
@@ -237,7 +237,7 @@
X 	self->daddr = daddr;
X 	ASSERT(self->saddr == saddr, return;);
X 
-	irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb);
+	irlmp_do_lap_event(self, LM_LAP_CONNECT_INDICATION, skb);
X }
X 
X /*
@@ -246,19 +246,19 @@
X  *    LAP connection confirmed!
X  *
X  */
-void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, 
-				 struct sk_buff *userdata)
+void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, 
+				struct sk_buff *userdata)
X {
-	DEBUG( 4, "irlmp_link_connect_confirm()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
-	ASSERT( qos != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(qos != NULL, return;);
X 
X 	/* Copy QoS settings for this session */
X 	self->qos = qos;
X 
-	irlmp_do_lap_event( self, LM_LAP_CONNECT_CONFIRM, NULL);
+	irlmp_do_lap_event(self, LM_LAP_CONNECT_CONFIRM, NULL);
X }
X 
X /*
@@ -276,7 +276,9 @@
X 	irlmp_add_discovery(irlmp->cachelog, discovery);
X 
X 	/* Just handle it the same way as a discovery confirm */
+#if 0
X 	irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL);
+#endif
X }
X 
X /*
@@ -365,7 +367,7 @@
X #endif
X 			return lsap;
X 		}
-		lsap = ( struct lsap_cb *) hashbin_get_next(queue);
+		lsap = (struct lsap_cb *) hashbin_get_next(queue);
X 	}
X 
X 	/* Sorry not found! */
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c
--- v2.2.9/linux/net/irda/irlpt/irlpt_cli.c	Tue May 11 13:10:32 1999
+++ linux/net/irda/irlpt/irlpt_cli.c	Sun May 30 10:17:04 1999
@@ -51,10 +51,11 @@
X static void irlpt_client_connect_confirm(void *instance, void *sap, 
X 					 struct qos_info *qos, 
X 					 __u32 max_seg_size, 
+					 __u8 max_header_size,
X 					 struct sk_buff *skb);
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
-						LM_REASON reason,
-						struct sk_buff *userdata);
+static void irlpt_client_disconnect_indication(void *instance, void *sap, 
+					       LM_REASON reason,
+					       struct sk_buff *userdata);
X static void irlpt_client_expired(unsigned long data);
X 
X #if 0
@@ -187,7 +188,7 @@
X 
X #ifdef CONFIG_PROC_FS
X 	create_proc_entry("irlpt_client", 0, proc_irda)->get_info
-			= irlpt_client_proc_read;
+		= irlpt_client_proc_read;
X #endif /* CONFIG_PROC_FS */
X 
X 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
@@ -215,7 +216,6 @@
X #ifdef CONFIG_PROC_FS
X 	remove_proc_entry("irlpt_client", proc_irda);
X #endif
-
X 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
X }
X #endif /* MODULE */
@@ -403,9 +403,8 @@
X 
X 	irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL);
X 
-	if (skb) {
+	if (skb)
X 		dev_kfree_skb( skb);
-	}
X 
X 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
X }
@@ -417,7 +416,8 @@
X  */
X static void irlpt_client_connect_confirm(void *instance, void *sap, 
X 					 struct qos_info *qos, 
-					 __u32 max_sdu_size,
+					 __u32 max_seg_size,
+					 __u8 max_header_size,
X 					 struct sk_buff *skb)
X {
X 	struct irlpt_info info;
@@ -443,14 +443,14 @@
X 	}
X #endif
X 
-	self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER);
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
X 	self->connected = TRUE;
X 	
X 	irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL);
X 
-	if (skb) {
+	if (skb)
X 		dev_kfree_skb( skb);
-	}
X 
X 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
X }
@@ -603,7 +603,7 @@
X 			return;
X 		}
X 
-		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(skb, LMP_MAX_HEADER);
X 		irlmp_disconnect_request(self->lsap, skb);
X 		DEBUG(irlpt_client_debug, __FUNCTION__
X 		      ": irlmp_close_slap(self->lsap)\n");
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_cli_fsm.c linux/net/irda/irlpt/irlpt_cli_fsm.c
--- v2.2.9/linux/net/irda/irlpt/irlpt_cli_fsm.c	Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irlpt/irlpt_cli_fsm.c	Sun May 30 10:17:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Tue Jan 26 12:02:31 1999
+ * Modified at:   Sun May  9 13:36:13 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>
+ *     Copyright (c) 1998-1999, Thomas Davis, <rat...@radiks.net>
X  *     Copyright (c) 1998, Dag Brattli, <da...@cs.uit.no>
X  *     All Rights Reserved.
X  *      
@@ -43,10 +43,10 @@
X 				      IRLPT_EVENT event,
X 				      struct sk_buff *skb, 
X 				      struct irlpt_info *info);
-static int irlpt_client_state_ready  ( struct irlpt_cb *self, 
-				       IRLPT_EVENT event, 
-				       struct sk_buff *skb, 
-				       struct irlpt_info *info);
+static int irlpt_client_state_ready ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event, 
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
X static int irlpt_client_state_waiti ( struct irlpt_cb *self, 
X 				      IRLPT_EVENT event,
X 				      struct sk_buff *skb, 
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
--- v2.2.9/linux/net/irda/irlpt/irlpt_common.c	Wed Mar 10 15:29:53 1999
+++ linux/net/irda/irlpt/irlpt_common.c	Sun May 30 10:17:04 1999
@@ -251,18 +251,18 @@
X 	}
X 
X 	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
-		count, self->irlap_data_size, IRLPT_MAX_HEADER);
+	       ": count = %d, max_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+		count, self->max_data_size, IRLPT_MAX_HEADER);
X 
- 	if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
- 		count = (self->irlap_data_size - IRLPT_MAX_HEADER);
+ 	if (count > self->max_data_size) {
+ 		count = self->max_data_size;
X  		DEBUG(irlpt_common_debug, __FUNCTION__ 
X 		      ": setting count to %d\n", count);
X  	}
X 
X 	DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count);
X 
-	skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
+	skb = dev_alloc_skb(count + self->max_header_size);
X 	if ( skb == NULL) {
X 		printk( KERN_INFO 
X 			__FUNCTION__ ": couldn't allocate skbuff!\n");
@@ -417,7 +417,7 @@
X 			return 0;
X 		}
X 
-		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve( skb, LMP_MAX_HEADER);
X 		irlmp_disconnect_request(self->lsap, skb);
X 		DEBUG(irlpt_common_debug, __FUNCTION__
X 		      ": irlmp_close_slap(self->lsap)\n");
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c
--- v2.2.9/linux/net/irda/irlpt/irlpt_srvr.c	Tue May 11 13:10:32 1999
+++ linux/net/irda/irlpt/irlpt_srvr.c	Sun May 30 10:17:04 1999
@@ -51,15 +51,21 @@
X static void irlpt_server_disconnect_indication(void *instance, void *sap, 
X 						LM_REASON reason,
X 						struct sk_buff *skb);
+
+#if 0
X static void irlpt_server_connect_confirm(void *instance, void *sap, 
X 					 struct qos_info *qos,  
X 					 __u32 max_seg_size,
+					 __u8 max_header_size,
X 					 struct sk_buff *skb);
X static void irlpt_server_connect_indication(void *instance, 
X 					    void *sap, 
X 					    struct qos_info *qos, 
X 					    __u32 max_seg_size,
+					    __u8 max_header_size,
X 					    struct sk_buff *skb);
+#endif
+
X static int irlpt_server_data_indication(void *instance, void *sap, 
X 					struct sk_buff *skb);
X static void register_irlpt_server(void);
@@ -161,7 +167,6 @@
X }
X 
X extern struct proc_dir_entry *proc_irda;
-
X #endif /* CONFIG_PROC_FS */
X 
X /*
@@ -171,9 +176,9 @@
X  *
X  */
X 
-/*int irlpt_init( struct device *dev) {*/
X __initfunc(int irlpt_server_init(void))
X {
+	struct irmanager_event mgr_event;
X 	__u16 hints;
X 
X 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -212,6 +217,10 @@
X 		= irlpt_server_proc_read;
X #endif /* CONFIG_PROC_FS */
X 
+	mgr_event.event = EVENT_IRLPT_START;
+        sprintf(mgr_event.devname, "%s", irlpt_server->ifname);
+        irmanager_notify(&mgr_event);
+
X 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
X 
X 	return 0;
@@ -225,6 +234,7 @@
X  */
X static void irlpt_server_cleanup(void)
X {
+	struct irmanager_event mgr_event;
X 	struct sk_buff *skb;
X 
X 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -245,6 +255,10 @@
X 	remove_proc_entry("irlpt_server", proc_irda);
X #endif
X 
+        mgr_event.event = EVENT_IRLPT_STOP;
+        sprintf( mgr_event.devname, "%s", irlpt_server->ifname);
+        irmanager_notify( &mgr_event);
+ 
X 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
X }
X 
@@ -304,6 +318,7 @@
X 					 void *sap, 
X 					 struct qos_info *qos,
X 					 __u32 max_seg_size,
+					 __u8 max_header_size,
X 					 struct sk_buff *skb)
X {
X 	struct irlpt_cb *self;
@@ -314,6 +329,9 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IRLPT_MAGIC, return;);
X 
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
+
X 	self->connected = TRUE;
X 
X 	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
@@ -329,6 +347,7 @@
X 					    void *sap, 
X 					    struct qos_info *qos, 
X 					    __u32 max_seg_size,
+					    __u8 max_header_size,
X 					    struct sk_buff *skb)
X {
X 	struct irlpt_cb *self;
@@ -343,14 +362,16 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IRLPT_MAGIC, return;);
X 
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
+
X 	self->connected = IRLPT_CONNECTED;
X 	self->eof = FALSE;
X 
X 	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
X 
-	if (skb) {
+	if (skb)
X 		dev_kfree_skb( skb);
-	}
X 
X 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
X }
diff -u --recursive --new-file v2.2.9/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.2.9/linux/net/irda/irmod.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irmod.c	Mon Jun  7 16:19:59 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Mon Apr 12 11:31:01 1999
+ * Modified at:   Fri May 14 13:46:02 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -45,7 +45,7 @@
X #include <net/irda/wrapper.h>
X #include <net/irda/timer.h>
X 
-extern struct proc_dir_entry proc_irda;
+extern struct proc_dir_entry *proc_irda;
X 
X struct irda_cb irda; /* One global instance */
X 
@@ -110,6 +110,7 @@
X EXPORT_SYMBOL(irttp_flow_request);
X EXPORT_SYMBOL(irttp_connect_request);
X EXPORT_SYMBOL(irttp_udata_request);
+EXPORT_SYMBOL(irttp_dup);
X 
X /* Main IrDA module */
X #ifdef CONFIG_IRDA_DEBUG
@@ -151,6 +152,7 @@
X EXPORT_SYMBOL(irlmp_disconnect_request);
X EXPORT_SYMBOL(irlmp_get_daddr);
X EXPORT_SYMBOL(irlmp_get_saddr);
+EXPORT_SYMBOL(irlmp_dup);
X EXPORT_SYMBOL(lmp_reasons);
X 
X /* Queue */
@@ -174,10 +176,15 @@
X EXPORT_SYMBOL(irda_device_setup);
X EXPORT_SYMBOL(irda_device_set_media_busy);
X EXPORT_SYMBOL(irda_device_txqueue_empty);
+
+EXPORT_SYMBOL(irda_device_init_dongle);
+EXPORT_SYMBOL(irda_device_register_dongle);
+EXPORT_SYMBOL(irda_device_unregister_dongle);
+
X EXPORT_SYMBOL(async_wrap_skb);
X EXPORT_SYMBOL(async_unwrap_char);
X EXPORT_SYMBOL(irda_start_timer);
-EXPORT_SYMBOL(irda_get_mtt);
+/* EXPORT_SYMBOL(irda_get_mtt); */
X EXPORT_SYMBOL(setup_dma);
X 
X #ifdef CONFIG_IRTTY
@@ -505,19 +512,28 @@
X #endif
X }
X 
-#ifdef MODULE
-#ifdef CONFIG_PROC_FS
+/*
+ * Function irda_proc_modcount (inode, fill)
+ *
+ *    Use by the proc file system functions to prevent the irda module
+ *    being removed while the use is standing in the net/irda directory
+ */
X void irda_proc_modcount(struct inode *inode, int fill)
X {
+#ifdef MODULE
+#ifdef CONFIG_PROC_FS
X 	if (fill)
X 		MOD_INC_USE_COUNT;
X 	else
X 		MOD_DEC_USE_COUNT;
-}
X #endif /* CONFIG_PROC_FS */
+#endif /* MODULE */
+}
+
+#ifdef MODULE
X 
X MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); 
+MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); 
X MODULE_PARM(irda_debug, "1l");
X 
X /*
diff -u --recursive --new-file v2.2.9/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.2.9/linux/net/irda/irproc.c	Tue May 11 13:10:32 1999
+++ linux/net/irda/irproc.c	Sun May 30 10:17:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Thomas Davis, <rat...@radiks.net>
X  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Tue Apr  6 19:07:06 1999
+ * Modified at:   Fri May  7 08:06:49 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>, 
+ *     Copyright (c) 1998-1999, Thomas Davis, <rat...@radiks.net>, 
X  *     All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
@@ -20,8 +20,6 @@
X  *     I, Thomas Davis, provide no warranty for any of this software. 
X  *     This material is provided "AS-IS" and at no charge. 
X  *     
- *     Portions lifted from the linux/fs/procfs/ files.
- *
X  ********************************************************************/
X 
X #include <linux/miscdevice.h>
@@ -44,28 +42,27 @@
X 			   int unused);
X extern int discovery_proc_read(char *buf, char **start, off_t offset, int len, 
X 			       int unused);
+static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
+			       int unused);
X 
-enum irda_directory_inos {
-	PROC_IRDA_LAP = 1,
-	PROC_IRDA_LMP,
-	PROC_IRDA_TTP,
-	PROC_IRDA_LPT,
-	PROC_IRDA_COMM,
- 	PROC_IRDA_IRDA_DEVICE,
-	PROC_IRDA_IRIAS
-};
+/* enum irda_directory_inos { */
+/* 	PROC_IRDA_LAP = 1, */
+/* 	PROC_IRDA_LMP, */
+/* 	PROC_IRDA_TTP, */
+/* 	PROC_IRDA_LPT, */
+/* 	PROC_IRDA_COMM, */
+/*  	PROC_IRDA_IRDA_DEVICE, */
+/* 	PROC_IRDA_IRIAS */
+/* }; */
X 
X struct irda_entry {
X 	char *name;
-	int (*fn)(char*,char**,off_t,int,int);
+	int (*fn)(char*, char**, off_t, int, int);
X };
X 
X struct proc_dir_entry *proc_irda;
-
+ 
X static struct irda_entry dir[] = {
-#if 0 
-	{"lpt", irlpt_proc_read},
-#endif
X 	{"discovery",	discovery_proc_read},
X 	{"irda_device",	irda_device_proc_read},
X 	{"irttp",	irttp_proc_read},
@@ -75,19 +72,22 @@
X };
X 
X #define IRDA_ENTRIES_NUM (sizeof(dir)/sizeof(dir[0]))
-
+ 
X /*
X  * Function irda_proc_register (void)
X  *
X  *    Register irda entry in /proc file system
X  *
X  */
-void irda_proc_register(void) {
+void irda_proc_register(void) 
+{
X 	int i;
+
X 	proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL);
X #ifdef MODULE
X 	proc_irda->fill_inode = &irda_proc_modcount;
X #endif /* MODULE */
+
X 	for (i=0;i<IRDA_ENTRIES_NUM;i++)
X 		create_proc_entry(dir[i].name,0,proc_irda)->get_info=dir[i].fn;
X }
@@ -98,9 +98,14 @@
X  *    Unregister irda entry in /proc file system
X  *
X  */
-void irda_proc_unregister(void) {
+void irda_proc_unregister(void) 
+{
X 	int i;
+
X 	for (i=0;i<IRDA_ENTRIES_NUM;i++)
X 		remove_proc_entry(dir[i].name, proc_irda);
+
X 	remove_proc_entry("net/irda", NULL);
X }
+
+
diff -u --recursive --new-file v2.2.9/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.2.9/linux/net/irda/irsysctl.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irsysctl.c	Sun May 30 10:17:04 1999
@@ -1,15 +1,15 @@
X /*********************************************************************
X  *                
X  * Filename:      irsysctl.c
- * Version:       
- * Description:   
+ * Version:       1.0
+ * Description:   Sysctl interface for IrDA
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Fri Apr 23 09:46:38 1999
+ * Modified at:   Thu May  6 21:32:46 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
diff -u --recursive --new-file v2.2.9/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.2.9/linux/net/irda/irttp.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irttp.c	Mon Jun  7 16:19:59 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Sat Apr 10 10:32:21 1999
+ * Modified at:   Mon May 31 10:29:56 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, 
X * All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
@@ -35,7 +35,7 @@
X #include <net/irda/irlmp.h>
X #include <net/irda/irttp.h>
X 
-struct irttp_cb *irttp = NULL;
+static struct irttp_cb *irttp = NULL;
X 
X static void __irttp_close_tsap(struct tsap_cb *self);
X 
@@ -44,19 +44,20 @@
X static int irttp_udata_indication(void *instance, void *sap, 
X 				  struct sk_buff *skb);
X static void irttp_disconnect_indication(void *instance, void *sap,  
-					LM_REASON reason,
-					struct sk_buff *);
+					LM_REASON reason, struct sk_buff *);
X static void irttp_connect_indication(void *instance, void *sap, 
X 				     struct qos_info *qos, __u32 max_sdu_size,
-				     struct sk_buff *skb);
-
+				     __u8 header_size, struct sk_buff *skb);
+static void irttp_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos, __u32 max_sdu_size, 
+				  __u8 header_size, struct sk_buff *skb);
X static void irttp_run_tx_queue(struct tsap_cb *self);
X static void irttp_run_rx_queue(struct tsap_cb *self);
X 
X static void irttp_flush_queues(struct tsap_cb *self);
X static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
-static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
X static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
X 
X /*
X  * Function irttp_init (void)
@@ -296,7 +297,7 @@
X 
X 	/* Check that nothing bad happens */
X 	if ((skb->len == 0) || (!self->connected)) {
-		DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
+		ERROR(__FUNCTION__ "(), No data, or not connected\n");
X 		return -ENOTCONN;
X 	}
X 
@@ -305,8 +306,8 @@
X 	 *  inside an IrLAP frame
X 	 */
X 	if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
-		DEBUG(1, __FUNCTION__ 
-		       "(), SAR disabled, and data is to large for IrLAP!\n");
+		ERROR(__FUNCTION__ 
+		      "(), SAR disabled, and data is to large for IrLAP!\n");
X 		return -EMSGSIZE;
X 	}
X 
@@ -318,8 +319,8 @@
X 	    (self->tx_max_sdu_size != SAR_UNBOUND) && 
X 	    (skb->len > self->tx_max_sdu_size))
X 	{
-		DEBUG(1, __FUNCTION__ "(), SAR enabled, "
-		       "but data is larger than TxMaxSduSize!\n");
+		ERROR(__FUNCTION__ "(), SAR enabled, "
+		      "but data is larger than TxMaxSduSize!\n");
X 		return -EMSGSIZE;
X 	}
X 	/* 
@@ -337,10 +338,10 @@
X 	/* Queue frame, or queue frame segments */
X 	if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
X 		/* Queue frame */
+		ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;);
X 		frame = skb_push(skb, TTP_HEADER);
X 		frame[0] = 0x00; /* Clear more bit */
X 		
-		DEBUG(4, __FUNCTION__ "(), queueing original skb\n");
X 		skb_queue_tail(&self->tx_queue, skb);
X 	} else {
X 		/*
@@ -360,8 +361,8 @@
X 		self->tx_sdu_busy = TRUE;
X 		
X 	 	if (self->notify.flow_indication) {
- 			self->notify.flow_indication(
-				self->notify.instance, self, FLOW_STOP);
+ 			self->notify.flow_indication(self->notify.instance, 
+						     self, FLOW_STOP);
X 		}
X  	}
X 	
@@ -381,12 +382,8 @@
X {
X 	struct sk_buff *skb = NULL;
X 	unsigned long flags;
-	__u8 *frame;
X 	int n;
X 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
-	
X 	if (irda_lock(&self->tx_queue_lock) == FALSE)
X 		return;
X 
@@ -421,12 +418,7 @@
X 		 *  More bit must be set by the data_request() or fragment() 
X 		 *  functions
X 		 */
-		frame = skb->data;
-
-		DEBUG(4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
-		       "TRUE" : "FALSE" );
-
-		frame[0] |= (__u8) (n & 0x7f);
+		skb->data[0] |= (n & 0x7f);
X 		
X 		irlmp_data_request(self->lsap, skb);
X 		self->stats.tx_packets++;
@@ -434,12 +426,12 @@
X 		/* Check if we can accept more frames from client */
X 		if ((self->tx_sdu_busy) && 
X 		    (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) 
-		{ 
+		{
X 			self->tx_sdu_busy = FALSE;
X 			
X 			if (self->notify.flow_indication)
X 				self->notify.flow_indication(
-					self->notify.instance, self, 
+					self->notify.instance, self,
X 					FLOW_START);
X 		}
X 	}
@@ -472,7 +464,7 @@
X 		return;
X 
X 	/* Reserve space for LMP, and LAP header */
-	skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER);
+	skb_reserve(tx_skb, self->max_header_size);
X 
X 	/*
X 	 *  Since we can transmit and receive frames concurrently, 
@@ -538,23 +530,14 @@
X 				 struct sk_buff *skb)
X {
X 	struct tsap_cb *self;
-	int more;
X 	int n;
-	__u8 *frame;
-	
+
X 	self = (struct tsap_cb *) instance;
X 
X 	ASSERT(self != NULL, return -1;);
X 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
-	ASSERT(skb != NULL, return -1;);
X 
-	frame = skb->data;
-	
-	n = frame[0] & 0x7f;     /* Extract the credits */
-	more = frame[0] & 0x80;
-
- 	DEBUG(3, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
-	      n, self->stsap_sel);
+	n = skb->data[0] & 0x7f;     /* Extract the credits */
X 
X 	self->stats.rx_packets++;
X 
@@ -562,10 +545,9 @@
X 	 *  Data or dataless frame? Dataless frames only contain the 
X 	 *  TTP_HEADER
X 	 */
-	if (skb->len == 1) {
-		/* Dataless flowdata TTP-PDU */
-		self->send_credit += n;
-	} else {
+	if (skb->len == 1)
+		self->send_credit += n;	/* Dataless flowdata TTP-PDU */
+	else {
X 		/* Deal with inbound credit */
X 		self->send_credit += n;
X 		self->remote_credit--;
@@ -655,15 +637,14 @@
X 			return -ENOMEM;
X 		
X 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, TTP_MAX_HEADER);
X 	} else {
X 		skb = userdata;
X 		/*  
X 		 *  Check that the client has reserved enough space for 
X 		 *  headers
X 		 */
-		ASSERT(skb_headroom(userdata) >= 
-		       (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return -1;);
+		ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;);
X 	}
X 
X 	/* Initialize connection parameters */
@@ -691,12 +672,11 @@
X 
X 	/* SAR enabled? */
X 	if (max_sdu_size > 0) {
-		ASSERT(skb_headroom(skb) >= 
-			(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
-			return -1;);
+		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER), 
+		       return -1;);
X 
X 		/* Insert SAR parameters */
-		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
X 		
X 		frame[0] = TTP_PARAMETERS | n; 
X 		frame[1] = 0x04; /* Length */
@@ -724,8 +704,10 @@
X  *    Sevice user confirms TSAP connection with peer. 
X  *
X  */
-void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
-			   __u32 max_seg_size, struct sk_buff *skb) 
+static void irttp_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos,
+				  __u32 max_seg_size, __u8 max_header_size,
+				  struct sk_buff *skb) 
X {
X 	struct tsap_cb *self;
X 	int parameters;
@@ -741,7 +723,8 @@
X 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
X 	ASSERT(skb != NULL, return;);
X 
-	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
+	self->max_seg_size = max_seg_size;
+	self->max_header_size = max_header_size + TTP_HEADER;
X 
X 	/*
X 	 *  Check if we have got some QoS parameters back! This should be the
@@ -764,6 +747,10 @@
X 	self->connected = TRUE;
X 
X 	parameters = frame[0] & 0x80;	
+
+	ASSERT(skb->len >= TTP_HEADER, return;);
+	skb_pull(skb, TTP_HEADER);
+		
X 	if (parameters) {
X 		plen = frame[1];
X 		pi   = frame[2];
@@ -789,17 +776,19 @@
X 
X 		DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
X 		      self->tx_max_sdu_size);
+		
+		/* Remove parameters */
+		ASSERT(skb->len >= (plen+1), return;);
+		skb_pull(skb, plen+1);
X 	}
X 	
X 	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
X 	      self->send_credit, self->avail_credit, self->remote_credit);
X 
-	skb_pull(skb, TTP_HEADER);
-
X 	if (self->notify.connect_confirm) {
-		self->notify.connect_confirm(self->notify.instance, self, 
-					     qos, self->tx_max_sdu_size, 
-					     skb);
+		self->notify.connect_confirm(self->notify.instance, self, qos,
+					     self->tx_max_sdu_size, 
+					     self->max_header_size, skb);
X 	}
X }
X 
@@ -809,8 +798,8 @@
X  *    Some other device is connecting to this TSAP
X  *
X  */
-void irttp_connect_indication(void *instance, void *sap, 
-			      struct qos_info *qos, __u32 max_seg_size, 
+void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      __u32 max_seg_size, __u8 max_header_size, 
X 			      struct sk_buff *skb) 
X {
X 	struct tsap_cb *self;
@@ -828,7 +817,9 @@
X 
X 	lsap = (struct lsap_cb *) sap;
X 
-	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
+	self->max_seg_size = max_seg_size;
+
+	self->max_header_size = max_header_size+TTP_HEADER;
X 
X 	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
X 
@@ -841,7 +832,11 @@
X 	self->send_credit = n;
X 	self->tx_max_sdu_size = 0;
X 	
-	parameters = frame[0] & 0x80;	
+	parameters = frame[0] & 0x80;
+
+	ASSERT(skb->len >= TTP_HEADER, return;);
+	skb_pull(skb, TTP_HEADER);
+		
X 	if (parameters) {
X 		DEBUG(3, __FUNCTION__ "(), Contains parameters!\n");
X 		plen = frame[1];
@@ -850,7 +845,7 @@
X 
X 		switch (pl) {
X 		case 1:
-			self->tx_max_sdu_size = *(frame+4);
+			self->tx_max_sdu_size = frame[4];
X 			break;
X 		case 2:
X 			self->tx_max_sdu_size = 
@@ -865,7 +860,10 @@
X 			       "() illegal value length for max_sdu_size!\n");
X 			self->tx_max_sdu_size = 0;
X 		};
-
+		
+		/* Remove parameters */
+		ASSERT(skb->len >= (plen+1), return;);
+		skb_pull(skb, plen+1);
X 
X 		DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n", 
X 		      self->tx_max_sdu_size);
@@ -873,12 +871,10 @@
X 
X 	DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
X 
-	skb_pull(skb, 1); /* Remove TTP header */
-
X 	if (self->notify.connect_indication) {
X 		self->notify.connect_indication(self->notify.instance, self, 
X 						qos, self->rx_max_sdu_size, 
-						skb);
+						self->max_header_size, skb);
X 	}
X }
X 
@@ -909,15 +905,14 @@
X 			return;
X 
X 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, TTP_MAX_HEADER);
X 	} else {
X 		skb = userdata;
X 		/*  
X 		 *  Check that the client has reserved enough space for 
X 		 *  headers
X 		 */
-		ASSERT(skb_headroom(skb) >= 
-			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
+		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;);
X 	}
X 	
X 	self->avail_credit = 0;
@@ -939,12 +934,11 @@
X 
X 	/* SAR enabled? */
X 	if (max_sdu_size > 0) {
-		ASSERT(skb_headroom(skb) >= 
-		       (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
+		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER), 
X 		       return;);
X 		
X 		/* Insert TTP header with SAR parameters */
-		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
X 		
X 		frame[0] = TTP_PARAMETERS | n;
X 		frame[1] = 0x04; /* Length */
@@ -1079,7 +1073,7 @@
X 		/* 
X 		 *  Reserve space for MUX and LAP header 
X 		 */
-		skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(skb, TTP_MAX_HEADER);
X 		
X 		userdata = skb;
X 	}
@@ -1357,13 +1351,11 @@
X 		}
X 		
X 		/* Make new segment */
-		frag = dev_alloc_skb(self->max_seg_size+
-				      TTP_HEADER+LMP_HEADER+
-				      LAP_HEADER);
+		frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
X 		if (!frag)
X 			return;
X 
-		skb_reserve(frag, LMP_HEADER+LAP_HEADER);
+		skb_reserve(frag, self->max_header_size);
X 
X 		/*
X 		 *  Copy data from the original skb into this fragment. We
@@ -1401,11 +1393,9 @@
X 	irttp_run_tx_queue(self);
X 
X 	/*  Give avay some credits to peer?  */
-	if ((skb_queue_empty(&self->tx_queue)) && 
-	    (self->remote_credit < LOW_THRESHOLD) && 
-	    (self->avail_credit > 0)) 
+	if ((self->remote_credit < LOW_THRESHOLD) && 
+	    (self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
X 	{
-		DEBUG(4, __FUNCTION__ "(), sending credit!\n");
X 		irttp_give_credit(self);
X 	}
X 
diff -u --recursive --new-file v2.2.9/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.2.9/linux/net/irda/qos.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/qos.c	Sun May 30 10:17:04 1999
@@ -6,10 +6,11 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Mon Apr 12 11:49:24 1999
+ * Modified at:   Mon May  3 21:15:08 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, 
+ *     All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -52,10 +53,10 @@
X  *    Compute the intersection of the old QoS capabilites with new ones
X  *
X  */
-void irda_qos_compute_intersection( struct qos_info *qos, struct qos_info *new)
+void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
X {
-	ASSERT( qos != NULL, return;);
-	ASSERT( new != NULL, return;);
+	ASSERT(qos != NULL, return;);
+	ASSERT(new != NULL, return;);
X 
X 	/* Apply */
X 	qos->baud_rate.bits       &= new->baud_rate.bits;
diff -u --recursive --new-file v2.2.9/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.2.9/linux/net/irda/wrapper.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/wrapper.c	Mon Jun  7 16:19:59 1999
@@ -1,15 +1,15 @@
X /*********************************************************************
X  *                
X  * Filename:      wrapper.c
- * Version:       1.1
- * Description:   SIR wrapper layer
+ * Version:       1.2
+ * Description:   IrDA SIR async wrapper layer
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Apr 21 12:45:55 1999
+ * Modified at:   Fri May 28 20:30:24 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, 
X * All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
@@ -34,7 +34,20 @@
X #include <net/irda/irlap_frame.h>
X #include <net/irda/irda_device.h>
X 
-inline static int stuff_byte(__u8 byte, __u8 *buf);
+static inline int stuff_byte(__u8 byte, __u8 *buf);
+
+static void state_outside_frame(struct irda_device *idev, __u8 byte);
+static void state_begin_frame(struct irda_device *idev, __u8 byte);
+static void state_link_escape(struct irda_device *idev, __u8 byte);
+static void state_inside_frame(struct irda_device *idev, __u8 byte);
+
+static void (*state[])(struct irda_device *idev, __u8 byte) = 
+{ 
+	state_outside_frame,
+	state_begin_frame,
+	state_link_escape,
+	state_inside_frame,
+};
X 
X /*
X  * Function async_wrap (skb, *tx_buff)
@@ -52,8 +65,6 @@
X 		__u8 bytes[2];
X 	} fcs;
X 
-	ASSERT(skb != NULL, return 0;);
-
X 	/* Initialize variables */
X 	fcs.value = INIT_FCS;
X 	n = 0;
@@ -74,13 +85,9 @@
X 	} else
X 		xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
X 
-#if 0
- 	for (i=0; i<xbofs; i++)
-  		tx_buff[n++] = XBOF;
-#else
X 	memset(tx_buff+n, XBOF, xbofs);
X 	n += xbofs;
-#endif
+
X 	/* Start of packet character BOF */
X 	tx_buff[n++] = BOF;
X 
@@ -94,7 +101,7 @@
X 		ASSERT(n < (buffsize-5), return n;);
X 
X 		n += stuff_byte(skb->data[i], tx_buff+n);
-		fcs.value = IR_FCS(fcs.value, skb->data[i]);
+		fcs.value = irda_fcs(fcs.value, skb->data[i]);
X 	}
X 	
X 	/* Insert CRC in little endian format (LSB first) */
@@ -108,15 +115,6 @@
X #endif
X 	tx_buff[n++] = EOF;
X 
-#if 0
-	{
-		int i;
-		
-		for (i=0;i<n;i++)
-			printk("%02x", tx_buff[i]);
-		printk("\n");
-	}
-#endif
X 	return n;
X }
X 
@@ -155,147 +153,13 @@
X }
X 
X /*
- * Function async_unwrap (skb)
- *
- *    Parse and de-stuff frame received from the IR-port
- *
- */
-void async_unwrap_char(struct irda_device *idev, __u8 byte) 
-{
-	/* State machine for receiving frames */	   
-	switch (idev->rx_buff.state) {
-	case OUTSIDE_FRAME:
-		switch(byte) {
-		case BOF:
-			idev->rx_buff.state = BEGIN_FRAME;
-			idev->rx_buff.in_frame = TRUE;
-			break;
-		case XBOF:
-			/* idev->xbofs++; */
-			break;
-		case EOF:
-			irda_device_set_media_busy( idev, TRUE);
-			break;
-		default:
-			break;
-		}
-		break;
-	case BEGIN_FRAME:
-		switch (byte) {
-		case BOF:
-			/* Continue */
-			break;
-		case CE:
-			/* Stuffed byte */
-			idev->rx_buff.state = LINK_ESCAPE;
-			break;
-		case EOF:
-			/* Abort frame */
-			idev->rx_buff.state = OUTSIDE_FRAME;
-
-			idev->stats.rx_errors++;
-			idev->stats.rx_frame_errors++;
-			break;
-		default:
-			/* Got first byte of frame */
-			idev->rx_buff.data = idev->rx_buff.head;
-			idev->rx_buff.len = 0;
-
-			idev->rx_buff.data[idev->rx_buff.len++] = byte;
-			
-			idev->rx_buff.fcs = IR_FCS(INIT_FCS, byte);
-			idev->rx_buff.state = INSIDE_FRAME;
-			break;
-		}
-		break;
-	case LINK_ESCAPE:
-		switch (byte) {
-		case BOF:
-			/* New frame? */
-			idev->rx_buff.state = BEGIN_FRAME;
-			irda_device_set_media_busy(idev, TRUE);
-			break;
-		case CE:
-			DEBUG(4, "WARNING: State not defined\n");
-			break;
-		case EOF:
-			/* Abort frame */
-			idev->rx_buff.state = OUTSIDE_FRAME;
-			break;
-		default:
-			/* 
-			 *  Stuffed char, complement bit 5 of byte 
-			 *  following CE, IrLAP p.114 
-			 */
-			byte ^= IR_TRANS;
-			if (idev->rx_buff.len < idev->rx_buff.truesize)  {
-				idev->rx_buff.data[idev->rx_buff.len++] = byte;
-				idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs,
-							   byte);
-				idev->rx_buff.state = INSIDE_FRAME;
-			} else {
-				DEBUG(1, __FUNCTION__ 
-				       "(), Rx buffer overflow, aborting\n");
-				idev->rx_buff.state = OUTSIDE_FRAME;
-			}
-			break;
-		}
-		break;
-	case INSIDE_FRAME:
-		switch (byte) {
-		case BOF:
-			/* New frame? */
-			idev->rx_buff.state = BEGIN_FRAME;
-			irda_device_set_media_busy(idev, TRUE);
-			break;
-		case CE:
-			/* Stuffed char */
-			idev->rx_buff.state = LINK_ESCAPE;
-			break;
-		case EOF:
-			/* End of frame */
-			idev->rx_buff.state = OUTSIDE_FRAME;
-			idev->rx_buff.in_frame = FALSE;
-			
-			/* 
-			 *  Test FCS and deliver frame if it's good
-			 */			
-			if (idev->rx_buff.fcs == GOOD_FCS) {
-				async_bump(idev, idev->rx_buff.data, 
-					   idev->rx_buff.len);
-			} else {
-				/* Wrong CRC, discard frame!  */
-				irda_device_set_media_busy(idev, TRUE); 
-
-				idev->stats.rx_errors++;
-				idev->stats.rx_crc_errors++;
-			}			
-			break;
-		default:
-			/* Next byte of frame */
-			if (idev->rx_buff.len < idev->rx_buff.truesize)  {
-				idev->rx_buff.data[idev->rx_buff.len++] = byte;
-				idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs,
-							   byte);
-			} else {
-				DEBUG(1, __FUNCTION__ 
-				      "(), Rx buffer overflow, aborting\n");
-				idev->rx_buff.state = OUTSIDE_FRAME;
-			}
-			break;
-		}
-		break;
-	}
-}
- 
-/*
X  * Function stuff_byte (byte, buf)
X  *
X  *    Byte stuff one single byte and put the result in buffer pointed to by
X  *    buf. The buffer must at all times be able to have two bytes inserted.
X  * 
X  */
-inline static int stuff_byte(__u8 byte, __u8 *buf) 
+static inline int stuff_byte(__u8 byte, __u8 *buf) 
X {
X 	switch (byte) {
X 	case BOF: /* FALLTHROUGH */
@@ -303,7 +167,7 @@
X 	case CE:
X 		/* Insert transparently coded */
X 		buf[0] = CE;               /* Send link escape */
-		buf[1] = byte^IR_TRANS;    /* Complement bit 5 */
+		buf[1] = byte^IRDA_TRANS;    /* Complement bit 5 */
X 		return 2;
X 		/* break; */
X 	default:
@@ -313,7 +177,163 @@
X 		/* break; */
X 	}
X }
+
+/*
+ * Function async_unwrap (skb)
+ *
+ *    Parse and de-stuff frame received from the IrDA-port
+ *
+ */
+inline void async_unwrap_char(struct irda_device *idev, __u8 byte)
+{
+	(*state[idev->rx_buff.state]) (idev, byte);
+}
X 	 
+/*
+ * Function state_outside_frame (idev, byte)
+ *
+ *    
+ *
+ */
+static void state_outside_frame(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF:
+		idev->rx_buff.state = BEGIN_FRAME;
+		idev->rx_buff.in_frame = TRUE;
+		break;
+	case XBOF:
+		/* idev->xbofs++; */
+		break;
+	case EOF:
+		irda_device_set_media_busy( idev, TRUE);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * Function state_begin_frame (idev, byte)
+ *
+ *    Begin of frame detected
+ *
+ */
+static void state_begin_frame(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF:
+		/* Continue */
+		break;
+	case CE:
+		/* Stuffed byte */
+		idev->rx_buff.state = LINK_ESCAPE;
+
+		/* Time to initialize receive buffer */
+		idev->rx_buff.data = idev->rx_buff.head;
+		idev->rx_buff.len = 0;
+		break;
+	case EOF:
+		/* Abort frame */
+		idev->rx_buff.state = OUTSIDE_FRAME;
+		
+		idev->stats.rx_errors++;
+		idev->stats.rx_frame_errors++;
+		break;
+	default:	
+		/* Time to initialize receive buffer */
+		idev->rx_buff.data = idev->rx_buff.head;
+		idev->rx_buff.len = 0;
+
+		idev->rx_buff.data[idev->rx_buff.len++] = byte;
+		
+		idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
+		idev->rx_buff.state = INSIDE_FRAME;
+		break;
+	}
+}
X 
+/*
+ * Function state_link_escape (idev, byte)
+ *
+ *    
+ *
+ */
+static void state_link_escape(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF: /* New frame? */
+		idev->rx_buff.state = BEGIN_FRAME;
+		irda_device_set_media_busy(idev, TRUE);
+		break;
+	case CE:
+		DEBUG(4, "WARNING: State not defined\n");
+		break;
+	case EOF: /* Abort frame */
+		idev->rx_buff.state = OUTSIDE_FRAME;
+		break;
+	default:
+		/* 
+		 *  Stuffed char, complement bit 5 of byte 
+		 *  following CE, IrLAP p.114 
+		 */
+		byte ^= IRDA_TRANS;
+		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
+			idev->rx_buff.data[idev->rx_buff.len++] = byte;
+			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
+			idev->rx_buff.state = INSIDE_FRAME;
+		} else {
+			DEBUG(1, __FUNCTION__ 
+			      "(), Rx buffer overflow, aborting\n");
+			idev->rx_buff.state = OUTSIDE_FRAME;
+		}
+		break;
+	}
+}
+
+/*
+ * Function state_inside_frame (idev, byte)
+ *
+ *    Handle bytes received within a frame
+ *
+ */
+static void state_inside_frame(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF: /* New frame? */
+		idev->rx_buff.state = BEGIN_FRAME;
+		irda_device_set_media_busy(idev, TRUE);
+		break;
+	case CE: /* Stuffed char */
+		idev->rx_buff.state = LINK_ESCAPE;
+		break;
+	case EOF: /* End of frame */
+		idev->rx_buff.state = OUTSIDE_FRAME;
+		idev->rx_buff.in_frame = FALSE;
+		
+		/* Test FCS and deliver frame if it's good */
+		if (idev->rx_buff.fcs == GOOD_FCS) {
+			async_bump(idev, idev->rx_buff.data, 
+				   idev->rx_buff.len);
+		} else {
+			/* Wrong CRC, discard frame!  */
+			irda_device_set_media_busy(idev, TRUE); 
+			
+			idev->stats.rx_errors++;
+			idev->stats.rx_crc_errors++;
+		}			
+		break;
+	default: /* Must be the next byte of the frame */
+		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
+			idev->rx_buff.data[idev->rx_buff.len++] = byte;
+			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
+		} else {
+			DEBUG(1, __FUNCTION__ 
+			      "(), Rx buffer overflow, aborting\n");
+			idev->rx_buff.state = OUTSIDE_FRAME;
+		}
+		break;
+	}
+}
X 
X 
diff -u --recursive --new-file v2.2.9/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.2.9/linux/net/netlink/af_netlink.c	Fri Apr 16 14:47:31 1999
+++ linux/net/netlink/af_netlink.c	Wed Jun  2 11:29:28 1999
@@ -1,7 +1,7 @@
X /*
X * NETLINK Kernel-user communication protocol.
X  *
- * 		Authors:	Alan Cox <al...@cymru.net>
+ * 		Authors:	Alan Cox <al...@redhat.com>
X * Alexey Kuznetsov <kuz...@ms2.inr.ac.ru>
X  *
X  *		This program is free software; you can redistribute it and/or
@@ -203,7 +203,7 @@
X 	 */
X 
X 	while (netlink_locked(sk)) {
-		current->counter = 0;
+		current->policy |= SCHED_YIELD;
X 		schedule();
X 	}
X 
diff -u --recursive --new-file v2.2.9/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- v2.2.9/linux/net/netlink/netlink_dev.c	Sat Sep  5 16:46:42 1998
+++ linux/net/netlink/netlink_dev.c	Wed Jun  2 11:29:28 1999
@@ -2,7 +2,7 @@
X  * NETLINK	An implementation of a loadable kernel mode driver providing
X  *		multiple kernel/user space bidirectional communications links.
X  *
- * 		Author: 	Alan Cox <al...@cymru.net>
+ * 		Author: 	Alan Cox <al...@redhat.com>
X  *
X  *		This program is free software; you can redistribute it and/or
X  *		modify it under the terms of the GNU General Public License
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
echo 'File patch-2.2.10 is complete' &&
chmod 644 patch-2.2.10 ||
echo 'restore of patch-2.2.10 failed'
Cksum="`cksum < 'patch-2.2.10'`"
if ! test "2711436326 1251005" = "$Cksum"
then
	echo 'patch-2.2.10: original Checksum 2711436326 1251005, current one' "$Cksum" 
	rm -f _shar_wnt_.tmp
	rm -f _shar_seq_.tmp
	exit 1
fi
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo 'You have unpacked the last part.'
exit 0
#!/bin/sh
# this is part 21 of a 22 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.10 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 21; 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.10'
else
echo 'x - continuing with patch-2.2.10'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.10' &&
X 		return -ENOMEM;
X 	}
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	irlap_compressors = hashbin_new( HB_LOCAL);
-	if ( irlap_compressors == NULL) {
-		printk( KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
+	irlap_compressors = hashbin_new(HB_LOCAL);
+	if (irlap_compressors == NULL) {
+		printk(KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
X 		return -ENOMEM;
X 	}
X #endif
@@ -86,12 +91,12 @@
X 
X void irlap_cleanup(void)
X {
-	ASSERT( irlap != NULL, return;);
+	ASSERT(irlap != NULL, return;);
X 
-	hashbin_delete( irlap, (FREE_FUNC) __irlap_close);
+	hashbin_delete(irlap, (FREE_FUNC) __irlap_close);
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	hashbin_delete( irlap_compressors, (FREE_FUNC) kfree);
+	hashbin_delete(irlap_compressors, (FREE_FUNC) kfree);
X #endif
X }
X 
@@ -101,32 +106,32 @@
X  *    Initialize IrLAP layer
X  *
X  */
-struct irlap_cb *irlap_open( struct irda_device *irdev)
+struct irlap_cb *irlap_open(struct irda_device *irdev)
X {
X 	struct irlap_cb *self;
X 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 	
-	ASSERT( irdev != NULL, return NULL;);
-	ASSERT( irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
+	ASSERT(irdev != NULL, return NULL;);
+	ASSERT(irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
X 
X 	/* Initialize the irlap structure. */
-	self = kmalloc( sizeof( struct irlap_cb), GFP_KERNEL);
-	if ( self == NULL)
+ self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
+	if (self == NULL)
X 		return NULL;
X 	
-	memset( self, 0, sizeof(struct irlap_cb));
+	memset(self, 0, sizeof(struct irlap_cb));
X 	self->magic = LAP_MAGIC;
X 
X 	/* Make a binding between the layers */
X 	self->irdev = irdev;
X 	self->netdev = &irdev->netdev;
X 
-	irlap_next_state( self, LAP_OFFLINE);
+	irlap_next_state(self, LAP_OFFLINE);
X 
X 	/* Initialize transmitt queue */
-	skb_queue_head_init( &self->tx_list);
-	skb_queue_head_init( &self->wx_list);
+	skb_queue_head_init(&self->tx_list);
+	skb_queue_head_init(&self->wx_list);
X 
X 	/* My unique IrLAP device address! */
X 	get_random_bytes(&self->saddr, sizeof(self->saddr));
@@ -140,21 +145,21 @@
X 		self->caddr &= 0xfe;
X 	}
X 
-	init_timer( &self->slot_timer);
-	init_timer( &self->query_timer);
-	init_timer( &self->discovery_timer);
-	init_timer( &self->final_timer);		
-	init_timer( &self->poll_timer);
-	init_timer( &self->wd_timer);
-	init_timer( &self->backoff_timer);
+	init_timer(&self->slot_timer);
+	init_timer(&self->query_timer);
+	init_timer(&self->discovery_timer);
+	init_timer(&self->final_timer);		
+	init_timer(&self->poll_timer);
+	init_timer(&self->wd_timer);
+	init_timer(&self->backoff_timer);
X 
-	irlap_apply_default_connection_parameters( self);
+	irlap_apply_default_connection_parameters(self);
X 	
-	irlap_next_state( self, LAP_NDM);
+	irlap_next_state(self, LAP_NDM);
X 
-	hashbin_insert( irlap, (QUEUE *) self, self->saddr, NULL);
+	hashbin_insert(irlap, (QUEUE *) self, self->saddr, NULL);
X 
-	irlmp_register_link( self, self->saddr, &self->notify);
+	irlmp_register_link(self, self->saddr, &self->notify);
X 	
X 	return self;
X }
@@ -165,26 +170,26 @@
X  *    Remove IrLAP and all allocated memory. Stop any pending timers.
X  *
X  */
-static void __irlap_close( struct irlap_cb *self)
+static void __irlap_close(struct irlap_cb *self)
X {
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X 	/* Stop timers */
-	del_timer( &self->slot_timer);
-	del_timer( &self->query_timer);
-	del_timer( &self->discovery_timer);
-	del_timer( &self->final_timer);		
-	del_timer( &self->poll_timer);
-	del_timer( &self->wd_timer);
-	del_timer( &self->backoff_timer);
+	del_timer(&self->slot_timer);
+	del_timer(&self->query_timer);
+	del_timer(&self->discovery_timer);
+	del_timer(&self->final_timer);		
+	del_timer(&self->poll_timer);
+	del_timer(&self->wd_timer);
+	del_timer(&self->backoff_timer);
X 
-	irlap_flush_all_queues( self);
+	irlap_flush_all_queues(self);
X        
X 	self->irdev = NULL;
X 	self->magic = 0;
X 	
-	kfree( self);
+	kfree(self);
X }
X 
X /*
@@ -193,27 +198,27 @@
X  *    Remove IrLAP instance
X  *
X  */
-void irlap_close( struct irlap_cb *self) 
+void irlap_close(struct irlap_cb *self) 
X {
X 	struct irlap_cb *lap;
X 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 	
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
-	irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+	irlap_disconnect_indication(self, LAP_DISC_INDICATION);
X 
X 	irlmp_unregister_link(self->saddr);
X 	self->notify.instance = NULL;
X 
X 	/* Be sure that we manage to remove ourself from the hash */
-	lap = hashbin_remove( irlap, self->saddr, NULL);
-	if ( !lap) {
-		DEBUG( 1, __FUNCTION__ "(), Didn't find myself!\n");
+	lap = hashbin_remove(irlap, self->saddr, NULL);
+	if (!lap) {
+		DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
X 		return;
X 	}
-	__irlap_close( lap);
+	__irlap_close(lap);
X }
X 
X /*
@@ -243,7 +248,7 @@
X  */
X void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb) 
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 	
X 	irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
X }
@@ -324,23 +329,23 @@
X  *    Received some data that was sent unreliable
X  *
X  */
-void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_unit_data_indication(struct irlap_cb *self, struct sk_buff *skb)
X {
-	DEBUG( 1, __FUNCTION__ "()\n"); 
+	DEBUG(1, __FUNCTION__ "()\n"); 
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
X 
X 	/* Hide LAP header from IrLMP layer */
-	skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	if ( self->qos_tx.compression.value) {
+	if (self->qos_tx.compression.value) {
X 		
-		skb = irlap_decompress_frame( self, skb);
-		if ( !skb) {
-			DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
+		skb = irlap_decompress_frame(self, skb);
+		if (!skb) {
+			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
X 			return;
X 		}
X 	}
@@ -354,40 +359,35 @@
X  *    Queue data for transmission, must wait until XMIT state
X  *
X  */
-inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb,
+inline void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
X 				int reliable)
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
-       
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-
-	DEBUG( 4, __FUNCTION__ "(), tx_list=%d\n", 
-		   skb_queue_len( &self->tx_list));
+	ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	if ( self->qos_tx.compression.value) {
-		skb = irlap_compress_frame( self, skb);
-		if ( !skb) {
-			DEBUG( 1, __FUNCTION__ "(), Compress error!\n");
+	if (self->qos_tx.compression.value) {
+		skb = irlap_compress_frame(self, skb);
+		if (!skb) {
+			DEBUG(1, __FUNCTION__ "(), Compress error!\n");
X 			return;
X 		}
X 	}
X #endif
X 	
-	ASSERT( skb_headroom( skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
-		return;);
-	skb_push( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
+	       return;);
+	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
X 
X 	/*  
X 	 *  Must set frame format now so that the rest of the code knows 
X 	 *  if its dealing with an I or an UI frame
X 	 */
-	if ( reliable)
+	if (reliable)
X 		skb->data[1] = I_FRAME;
X 	else {
-		DEBUG( 4, __FUNCTION__ "(), queueing unreliable frame\n");
+		DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
X 		skb->data[1] = UI_FRAME;
X 	}
X 
@@ -395,20 +395,20 @@
X 	 *  Send event if this frame only if we are in the right state 
X 	 *  FIXME: udata should be sent first! (skb_queue_head?)
X 	 */
-  	if (( self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
+  	if ((self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
X 		/*
X 		 *  Check if the transmit queue contains some unsent frames,
X 		 *  and if so, make sure they are sent first
X 		 */
-		if ( !skb_queue_empty( &self->tx_list)) {
-			skb_queue_tail( &self->tx_list, skb);
-			skb = skb_dequeue( &self->tx_list);
+		if (!skb_queue_empty(&self->tx_list)) {
+			skb_queue_tail(&self->tx_list, skb);
+			skb = skb_dequeue(&self->tx_list);
X 			
-			ASSERT( skb != NULL, return;);
+			ASSERT(skb != NULL, return;);
X 		}
-		irlap_do_event( self, SEND_I_CMD, skb, NULL);
+		irlap_do_event(self, SEND_I_CMD, skb, NULL);
X 	} else
-		skb_queue_tail( &self->tx_list, skb);	
+		skb_queue_tail(&self->tx_list, skb);	
X }
X 
X /*
@@ -444,33 +444,33 @@
X  *    Disconnect request from other device
X  *
X  */
-void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason) 
+void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason) 
X {
-	DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
+	DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	irda_free_compression( self);
+	irda_free_compression(self);
X #endif
X 	/* Flush queues */
-	irlap_flush_all_queues( self);
+	irlap_flush_all_queues(self);
X 	
-	switch( reason) {
+	switch(reason) {
X 	case LAP_RESET_INDICATION:
-		DEBUG( 1, __FUNCTION__ "(), Sending reset request!\n");
-		irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+		DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
+		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
X 		break;
X 	case LAP_NO_RESPONSE:	   /* FALLTROUGH */	
X 	case LAP_DISC_INDICATION:  /* FALLTROUGH */
X 	case LAP_FOUND_NONE:       /* FALLTROUGH */
X 	case LAP_MEDIA_BUSY:
-		irlmp_link_disconnect_indication( self->notify.instance, 
+		irlmp_link_disconnect_indication(self->notify.instance, 
X 						  self, reason, NULL);
X 		break;
X 	default:
-		DEBUG( 1, __FUNCTION__ "(), Reason %d not implemented!\n", 
+		DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
X 		       reason);
X 	}
X }
@@ -485,22 +485,22 @@
X {
X 	struct irlap_info info;
X 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( discovery != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(discovery != NULL, return;);
X 	
-	DEBUG( 4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
+	DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
X 
-	ASSERT(( discovery->nslots == 1) || ( discovery->nslots == 6) ||
-	       ( discovery->nslots == 8) || ( discovery->nslots == 16), 
+	ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
+	       (discovery->nslots == 8) || (discovery->nslots == 16), 
X 	       return;);
X 	
X   	/*
X 	 *  Discovery is only possible in NDM mode
X 	 */ 
-	if ( self->state == LAP_NDM) {
-		ASSERT( self->discovery_log == NULL, return;);
-		self->discovery_log= hashbin_new( HB_LOCAL);
+	if (self->state == LAP_NDM) {
+		ASSERT(self->discovery_log == NULL, return;);
+		self->discovery_log= hashbin_new(HB_LOCAL);
X 		
X 		info.S = discovery->nslots; /* Number of slots */
X 		info.s = 0; /* Current slot */
@@ -526,11 +526,11 @@
X 
X 		self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
X 		
-		irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info);
+		irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
X 	} else { 
- 		DEBUG( 4, __FUNCTION__ 
+ 		DEBUG(4, __FUNCTION__ 
X 		       "(), discovery only possible in NDM mode\n");
-		irlap_discovery_confirm( self, NULL);
+		irlap_discovery_confirm(self, NULL);
X  	} 
X }
X 
@@ -540,12 +540,12 @@
X  *    A device has been discovered in front of this station, we
X  *    report directly to LMP.
X  */
-void irlap_discovery_confirm( struct irlap_cb *self, hashbin_t *discovery_log) 
+void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log) 
X {
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 	
-	ASSERT( self->notify.instance != NULL, return;);
+	ASSERT(self->notify.instance != NULL, return;);
X 	
X 	/* 
X 	 * Check for successful discovery, since we are then allowed to clear 
@@ -556,7 +556,7 @@
X 		irda_device_set_media_busy(self->irdev, FALSE);
X 	
X 	/* Inform IrLMP */
-	irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
+	irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
X 	
X 	/* 
X 	 *  IrLMP has now the responsibilities for the discovery_log 
@@ -572,13 +572,13 @@
X  */
X void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery) 
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( discovery != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(discovery != NULL, return;);
X 
-	ASSERT( self->notify.instance != NULL, return;);
+	ASSERT(self->notify.instance != NULL, return;);
X 	
X 	irlmp_link_discovery_indication(self->notify.instance, discovery);
X }
@@ -591,12 +591,12 @@
X  */
X void irlap_status_indication(int quality_of_link) 
X {
-	switch( quality_of_link) {
+	switch(quality_of_link) {
X 	case STATUS_NO_ACTIVITY:
-		printk( KERN_INFO "IrLAP, no activity on link!\n");
+		printk(KERN_INFO "IrLAP, no activity on link!\n");
X 		break;
X 	case STATUS_NOISY:
-		printk( KERN_INFO "IrLAP, noisy link!\n");
+		printk(KERN_INFO "IrLAP, noisy link!\n");
X 		break;
X 	default:
X 		break;
@@ -610,17 +610,17 @@
X  *    
X  *
X  */
-void irlap_reset_indication( struct irlap_cb *self)
+void irlap_reset_indication(struct irlap_cb *self)
X {
-	DEBUG( 1, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 	
-	if ( self->state == LAP_RESET_WAIT)
-		irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+	if (self->state == LAP_RESET_WAIT)
+		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
X 	else
-		irlap_do_event( self, RESET_RESPONSE, NULL, NULL);
+		irlap_do_event(self, RESET_RESPONSE, NULL, NULL);
X }
X 
X /*
@@ -631,7 +631,7 @@
X  */
X void irlap_reset_confirm(void)
X {
- 	DEBUG( 1, __FUNCTION__ "()\n");
+ 	DEBUG(1, __FUNCTION__ "()\n");
X }
X 
X /*
@@ -641,15 +641,15 @@
X  *    S = Number of slots (0 -> S-1)
X  *    s = Current slot
X  */
-int irlap_generate_rand_time_slot( int S, int s) 
+int irlap_generate_rand_time_slot(int S, int s) 
X {
X 	int slot;
X 	
-	ASSERT(( S - s) > 0, return 0;);
+	ASSERT((S - s) > 0, return 0;);
X 
X 	slot = s + jiffies % (S-s);
X 	
-	ASSERT(( slot >= s) || ( slot < S), return 0;);
+	ASSERT((slot >= s) || (slot < S), return 0;);
X 	
X 	return slot;
X }
@@ -661,51 +661,51 @@
X  *    not intuitive and you should not try to change it. If you think it
X  *    contains bugs, please mail a patch to the author instead.
X  */
-void irlap_update_nr_received( struct irlap_cb *self, int nr) 
+void irlap_update_nr_received(struct irlap_cb *self, int nr) 
X {
X 	struct sk_buff *skb = NULL;
X int count = 0;
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X 	/*
X          * Remove all the ack-ed frames from the window queue.
X          */
X 
-	DEBUG( 4, "--> wx_list=%d, va=%d, nr=%d\n", 
-	       skb_queue_len( &self->wx_list), self->va, nr);
+	DEBUG(4, "--> wx_list=%d, va=%d, nr=%d\n", 
+	       skb_queue_len(&self->wx_list), self->va, nr);
X 
X 	/* 
X 	 *  Optimize for the common case. It is most likely that the receiver
X 	 *  will acknowledge all the frames we have sent! So in that case we
X 	 *  delete all frames stored in window.
X 	 */
-	if ( nr == self->vs) {
-		while (( skb = skb_dequeue( &self->wx_list)) != NULL) {
+	if (nr == self->vs) {
+		while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
X 		     dev_kfree_skb(skb);
X 		}
X 		/* The last acked frame is the next to send minus one */
X 		self->va = nr - 1;
X 	} else {
X 		/* Remove all acknowledged frames in current window */
-		while (( skb_peek( &self->wx_list) != NULL) && 
-		       ((( self->va+1) % 8) != nr)) 
+		while ((skb_peek(&self->wx_list) != NULL) && 
+		       (((self->va+1) % 8) != nr)) 
X 		{
-			skb = skb_dequeue( &self->wx_list);
+			skb = skb_dequeue(&self->wx_list);
X 			dev_kfree_skb(skb);
X 			
X 			self->va = (self->va + 1) % 8;
X 			count++;
X 		}
X 		
-		DEBUG( 4, "irlap_update_nr_received(), removed %d\n", count);
-		DEBUG( 4, "wx_list=%d, va=%d, nr=%d -->\n", 
-		       skb_queue_len( &self->wx_list), self->va, nr);
+		DEBUG(4, "irlap_update_nr_received(), removed %d\n", count);
+		DEBUG(4, "wx_list=%d, va=%d, nr=%d -->\n", 
+		       skb_queue_len(&self->wx_list), self->va, nr);
X 	}
X 	
X 	/* Advance window */
-	self->window = self->window_size - skb_queue_len( &self->wx_list);
+	self->window = self->window_size - skb_queue_len(&self->wx_list);
X }
X 
X /*
@@ -713,14 +713,14 @@
X  *
X  *    Validate the next to send (ns) field from received frame.
X  */
-int irlap_validate_ns_received( struct irlap_cb *self, int ns) 
+int irlap_validate_ns_received(struct irlap_cb *self, int ns) 
X {
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	ASSERT(self != NULL, return -ENODEV;);
+	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
X 
X 	/*  ns as expected?  */
-	if ( ns == self->vr) {
-		DEBUG( 4, __FUNCTION__ "(), expected!\n");
+	if (ns == self->vr) {
+		DEBUG(4, __FUNCTION__ "(), expected!\n");
X 		return NS_EXPECTED;
X 	}
X 	/*
@@ -737,14 +737,14 @@
X  *    Validate the next to receive (nr) field from received frame.
X  *
X  */
-int irlap_validate_nr_received( struct irlap_cb *self, int nr) 
+int irlap_validate_nr_received(struct irlap_cb *self, int nr) 
X {
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	ASSERT(self != NULL, return -ENODEV;);
+	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
X 
X 	/*  nr as expected?  */
-	if ( nr == self->vs) {
-		DEBUG( 4, __FUNCTION__ "(), expected!\n");
+	if (nr == self->vs) {
+		DEBUG(4, __FUNCTION__ "(), expected!\n");
X 		return NR_EXPECTED;
X 	}
X 
@@ -752,11 +752,11 @@
X 	 *  unexpected nr? (but within current window), first we check if the 
X 	 *  ns numbers of the frames in the current window wrap.
X 	 */
-	if ( self->va < self->vs) {
-		if (( nr >= self->va) && ( nr <= self->vs))
+	if (self->va < self->vs) {
+		if ((nr >= self->va) && (nr <= self->vs))
X 			return NR_UNEXPECTED;
X 	} else {
-		if (( nr >= self->va) || ( nr <= self->vs)) 
+		if ((nr >= self->va) || (nr <= self->vs)) 
X 			return NR_UNEXPECTED;
X 	}
X 	
@@ -770,12 +770,12 @@
X  *    Initialize the connection state parameters
X  *
X  */
-void irlap_initiate_connection_state( struct irlap_cb *self) 
+void irlap_initiate_connection_state(struct irlap_cb *self) 
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 	
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X 	/* Next to send and next to receive */
X 	self->vs = self->vr = 0;
@@ -829,24 +829,24 @@
X  *    Flush all queues
X  *
X  */
-void irlap_flush_all_queues( struct irlap_cb *self) 
+void irlap_flush_all_queues(struct irlap_cb *self) 
X {
X 	struct sk_buff* skb;
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X 	/* Free transmission queue */
-	while (( skb = skb_dequeue( &self->tx_list)) != NULL)
-		dev_kfree_skb( skb);
+	while ((skb = skb_dequeue(&self->tx_list)) != NULL)
+		dev_kfree_skb(skb);
X 	
X 	/* Free sliding window buffered packets */
-	while (( skb = skb_dequeue( &self->wx_list)) != NULL)
-		dev_kfree_skb( skb);
+	while ((skb = skb_dequeue(&self->wx_list)) != NULL)
+		dev_kfree_skb(skb);
X 
X #ifdef CONFIG_IRDA_RECYCLE_RR
-	if ( self->recycle_rr_skb) { 
- 		dev_kfree_skb( self->recycle_rr_skb);
+	if (self->recycle_rr_skb) { 
+ 		dev_kfree_skb(self->recycle_rr_skb);
X  		self->recycle_rr_skb = NULL;
X  	}
X #endif
@@ -866,7 +866,7 @@
X 	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X 	if (!self->irdev) {
-		DEBUG( 1, __FUNCTION__ "(), driver missing!\n");
+		DEBUG(1, __FUNCTION__ "(), driver missing!\n");
X 		return;
X 	}
X 
@@ -883,8 +883,8 @@
X 	__u8 mask; /* Current bit tested */
X 	int i;
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
X 	/* 
X 	 *  Find out which compressors we support. We do this be checking that
@@ -892,24 +892,24 @@
X 	 *  actually been loaded. Ths is sort of hairy code but that is what 
X 	 *  you get when you do a little bit flicking :-)
X 	 */
-	DEBUG( 4, __FUNCTION__ "(), comp bits 0x%02x\n", 
+	DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
X 	       self->qos_rx.compression.bits); 
X 	mask = 0x80; /* Start with testing MSB */
-	for ( i=0;i<8;i++) {
-		DEBUG( 4, __FUNCTION__ "(), testing bit %d\n", 8-i);
-		if ( self->qos_rx.compression.bits & mask) {
-			DEBUG( 4, __FUNCTION__ "(), bit %d is set by defalt\n",
+	for (i=0;i<8;i++) {
+		DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
+		if (self->qos_rx.compression.bits & mask) {
+			DEBUG(4, __FUNCTION__ "(), bit %d is set by defalt\n",
X 			       8-i);
-			comp = hashbin_find( irlap_compressors, 
+			comp = hashbin_find(irlap_compressors, 
X 					     compression[ msb_index(mask)], 
X 					     NULL);
-			if ( !comp) {
+			if (!comp) {
X 				/* Protocol not supported, so clear the bit */
-				DEBUG( 4, __FUNCTION__ "(), Compression "
+				DEBUG(4, __FUNCTION__ "(), Compression "
X 				       "protocol %d has not been loaded!\n", 
X 				       compression[msb_index(mask)]);
X 				self->qos_rx.compression.bits &= ~mask;
-				DEBUG( 4, __FUNCTION__ 
+				DEBUG(4, __FUNCTION__ 
X 				       "(), comp bits 0x%02x\n", 
X 				       self->qos_rx.compression.bits); 
X 			}
@@ -931,20 +931,20 @@
X void irlap_init_qos_capabilities(struct irlap_cb *self,
X 				 struct qos_info *qos_user)
X {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( self->irdev != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(self->irdev != NULL, return;);
X 
X 	/* Start out with the maximum QoS support possible */
-	irda_init_max_qos_capabilies( &self->qos_rx);
+	irda_init_max_qos_capabilies(&self->qos_rx);
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	irlap_init_comp_qos_capabilities( self);
+	irlap_init_comp_qos_capabilities(self);
X #endif
X 
X 	/* Apply drivers QoS capabilities */
-	irda_qos_compute_intersection( &self->qos_rx, 
-				       irda_device_get_qos( self->irdev));
+	irda_qos_compute_intersection(&self->qos_rx, 
+				      irda_device_get_qos(self->irdev));
X 
X 	/*
X 	 *  Check for user supplied QoS parameters. The service user is only 
@@ -952,17 +952,17 @@
X 	 *  user may not have set all of them.
X 	 */
X 	if (qos_user) {
-		DEBUG( 1, __FUNCTION__ "(), Found user specified QoS!\n");
+		DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
X 
-		if ( qos_user->baud_rate.bits)
+		if (qos_user->baud_rate.bits)
X 			self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
X 
-		if ( qos_user->max_turn_time.bits)
+		if (qos_user->max_turn_time.bits)
X 			self->qos_rx.max_turn_time.bits &= qos_user->max_turn_time.bits;
-		if ( qos_user->data_size.bits)
+		if (qos_user->data_size.bits)
X 			self->qos_rx.data_size.bits &= qos_user->data_size.bits;
X 
-		if ( qos_user->link_disc_time.bits)
+		if (qos_user->link_disc_time.bits)
X 			self->qos_rx.link_disc_time.bits &= qos_user->link_disc_time.bits;
X #ifdef CONFIG_IRDA_COMPRESSION
X 		self->qos_rx.compression.bits &= qos_user->compression.bits;
@@ -984,7 +984,7 @@
X 	/* Set disconnect time */
X 	self->qos_rx.link_disc_time.bits &= 0x07;
X 
-	irda_qos_bits_to_value( &self->qos_rx);
+	irda_qos_bits_to_value(&self->qos_rx);
X }
X 
X /*
@@ -993,14 +993,14 @@
X  *    Use the default connection and transmission parameters
X  * 
X  */
-void irlap_apply_default_connection_parameters( struct irlap_cb *self)
+void irlap_apply_default_connection_parameters(struct irlap_cb *self)
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
-	irlap_change_speed( self, 9600);
+	irlap_change_speed(self, 9600);
X 
X 	/* Default value in NDM */
X 	self->bofs_count = 11;
@@ -1028,12 +1028,12 @@
X void irlap_apply_connection_parameters(struct irlap_cb *self, 
X 				       struct qos_info *qos) 
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 	
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
X 
-	irlap_change_speed( self, qos->baud_rate.value);
+	irlap_change_speed(self, qos->baud_rate.value);
X 
X 	self->window_size = qos->window_size.value;
X 	self->window      = qos->window_size.value;
@@ -1045,7 +1045,7 @@
X 	 */
X 	self->window_bytes = qos->baud_rate.value 
X 		* qos->max_turn_time.value / 10000;
-	DEBUG( 4, "Setting window_bytes = %d\n", self->window_bytes);
+	DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
X 
X 	/*
X 	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
@@ -1058,10 +1058,10 @@
X 	else
X 		self->N1 = 3000 / qos->max_turn_time.value;
X 	
-	DEBUG( 4, "Setting N1 = %d\n", self->N1);
+	DEBUG(4, "Setting N1 = %d\n", self->N1);
X 	
X 	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
-	DEBUG( 4, "Setting N2 = %d\n", self->N2);
+	DEBUG(4, "Setting N2 = %d\n", self->N2);
X 
X 	/* 
X 	 *  Initialize timeout values, some of the rules are listed on 
@@ -1072,11 +1072,11 @@
X 	self->wd_timeout = self->poll_timeout * 2;
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-	if ( qos->compression.value) {
-		DEBUG( 1, __FUNCTION__ "(), Initializing compression\n");
-		irda_set_compression( self, qos->compression.value);
+	if (qos->compression.value) {
+		DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
+		irda_set_compression(self, qos->compression.value);
X 
-		irlap_compressor_init( self, 0);
+		irlap_compressor_init(self, 0);
X 	}
X #endif
X }
@@ -1088,7 +1088,7 @@
X  *    Give some info to the /proc file system
X  *
X  */
-int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
+int irlap_proc_read(char *buf, char **start, off_t offset, int len, 
X 		     int unused)
X {
X 	struct irlap_cb *self;
@@ -1100,81 +1100,81 @@
X 
X 	len = 0;
X 
-	self = (struct irlap_cb *) hashbin_get_first( irlap);
-	while ( self != NULL) {
-		ASSERT( self != NULL, return -ENODEV;);
-		ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	self = (struct irlap_cb *) hashbin_get_first(irlap);
+	while (self != NULL) {
+		ASSERT(self != NULL, return -ENODEV;);
+		ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
X 
-		len += sprintf( buf+len, "irlap%d <-> %s ",
+		len += sprintf(buf+len, "irlap%d <-> %s ",
X 				i++, self->irdev->name);
-		len += sprintf( buf+len, "state: %s\n", 
+		len += sprintf(buf+len, "state: %s\n", 
X 				irlap_state[ self->state]);
X 		
-		len += sprintf( buf+len, "  caddr: %#02x, ", self->caddr);
-		len += sprintf( buf+len, "saddr: %#08x, ", self->saddr);
-		len += sprintf( buf+len, "daddr: %#08x\n", self->daddr);
+		len += sprintf(buf+len, "  caddr: %#02x, ", self->caddr);
+		len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
+		len += sprintf(buf+len, "daddr: %#08x\n", self->daddr);
X 		
-		len += sprintf( buf+len, "  win size: %d, ", 
+		len += sprintf(buf+len, "  win size: %d, ", 
X 				self->window_size);
-		len += sprintf( buf+len, "win: %d, ", self->window);
-		len += sprintf( buf+len, "win bytes: %d, ", self->window_bytes);
-		len += sprintf( buf+len, "bytes left: %d\n", self->bytes_left);
-
-		len += sprintf( buf+len, "  tx queue len: %d ", 
-				skb_queue_len( &self->tx_list));
-		len += sprintf( buf+len, "win queue len: %d ", 
-				skb_queue_len( &self->wx_list));
-		len += sprintf( buf+len, "rbusy: %s\n", self->remote_busy ? 
+		len += sprintf(buf+len, "win: %d, ", self->window);
+		len += sprintf(buf+len, "win bytes: %d, ", self->window_bytes);
+		len += sprintf(buf+len, "bytes left: %d\n", self->bytes_left);
+
+		len += sprintf(buf+len, "  tx queue len: %d ", 
+				skb_queue_len(&self->tx_list));
+		len += sprintf(buf+len, "win queue len: %d ", 
+				skb_queue_len(&self->wx_list));
+		len += sprintf(buf+len, "rbusy: %s\n", self->remote_busy ? 
X 				"TRUE" : "FALSE");
X 		
-		len += sprintf( buf+len, "  retrans: %d ", self->retry_count);
-		len += sprintf( buf+len, "vs: %d ", self->vs);
-		len += sprintf( buf+len, "vr: %d ", self->vr);
-		len += sprintf( buf+len, "va: %d\n", self->va);
+		len += sprintf(buf+len, "  retrans: %d ", self->retry_count);
+		len += sprintf(buf+len, "vs: %d ", self->vs);
+		len += sprintf(buf+len, "vr: %d ", self->vr);
+		len += sprintf(buf+len, "va: %d\n", self->va);
X 		
-		len += sprintf( buf+len, "  qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
+		len += sprintf(buf+len, "  qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
X 		
-		len += sprintf( buf+len, "  tx\t%d\t", 
+		len += sprintf(buf+len, "  tx\t%d\t", 
X 				self->qos_tx.baud_rate.value);
-		len += sprintf( buf+len, "%d\t", 
+		len += sprintf(buf+len, "%d\t", 
X 				self->qos_tx.max_turn_time.value);
-		len += sprintf( buf+len, "%d\t",
+		len += sprintf(buf+len, "%d\t",
X 				self->qos_tx.data_size.value);
-		len += sprintf( buf+len, "%d\t",
+		len += sprintf(buf+len, "%d\t",
X 				self->qos_tx.window_size.value);
-		len += sprintf( buf+len, "%d\t",
+		len += sprintf(buf+len, "%d\t",
X 				self->qos_tx.additional_bofs.value);
-		len += sprintf( buf+len, "%d\t", 
+		len += sprintf(buf+len, "%d\t", 
X 				self->qos_tx.min_turn_time.value);
-		len += sprintf( buf+len, "%d\t", 
+		len += sprintf(buf+len, "%d\t", 
X 				self->qos_tx.link_disc_time.value);
X #ifdef CONFIG_IRDA_COMPRESSION
-		len += sprintf( buf+len, "%d",
+		len += sprintf(buf+len, "%d",
X 				self->qos_tx.compression.value);
X #endif
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "\n");
X 
-		len += sprintf( buf+len, "  rx\t%d\t", 
+		len += sprintf(buf+len, "  rx\t%d\t", 
X 				self->qos_rx.baud_rate.value);
-		len += sprintf( buf+len, "%d\t", 
+		len += sprintf(buf+len, "%d\t", 
X 				self->qos_rx.max_turn_time.value);
-		len += sprintf( buf+len, "%d\t",
+		len += sprintf(buf+len, "%d\t",
X 				self->qos_rx.data_size.value);
-		len += sprintf( buf+len, "%d\t",
+		len += sprintf(buf+len, "%d\t",
X 				self->qos_rx.window_size.value);
-		len += sprintf( buf+len, "%d\t",
+		len += sprintf(buf+len, "%d\t",
X 				self->qos_rx.additional_bofs.value);
-		len += sprintf( buf+len, "%d\t", 
+		len += sprintf(buf+len, "%d\t", 
X 				self->qos_rx.min_turn_time.value);
-		len += sprintf( buf+len, "%d\t", 
+		len += sprintf(buf+len, "%d\t", 
X 				self->qos_rx.link_disc_time.value);
X #ifdef CONFIG_IRDA_COMPRESSION
-		len += sprintf( buf+len, "%d",
+		len += sprintf(buf+len, "%d",
X 				self->qos_rx.compression.value);
X #endif
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "\n");
X 		
-		self = (struct irlap_cb *) hashbin_get_next( irlap);
+		self = (struct irlap_cb *) hashbin_get_next(irlap);
X 	}
X 	restore_flags(flags);
X 
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlap_comp.c linux/net/irda/irlap_comp.c
--- v2.2.9/linux/net/irda/irlap_comp.c	Wed Mar 10 15:29:52 1999
+++ linux/net/irda/irlap_comp.c	Sun May 30 10:17:04 1999
@@ -6,11 +6,11 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Mon Feb  8 01:23:52 1999
+ * Modified at:   Sun May  9 11:37:06 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       ppp.c, isdn_ppp.c
X  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
X  *      
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -255,11 +255,11 @@
X 	}
X 
X 	/* FIXME: Find out what is the max overhead (not 10) */
-	new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10);
+	new_skb = dev_alloc_skb( skb->len+LAP_MAX_HEADER+10);
X 	if(!new_skb)
X 		return skb;
X 
-	skb_reserve( new_skb, LAP_HEADER);
+	skb_reserve( new_skb, LAP_MAX_HEADER);
X 	skb_put( new_skb, skb->len+10);
X 	
X 	count = (self->compressor.cp->compress)( self->compressor.state, 
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.2.9/linux/net/irda/irlap_event.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irlap_event.c	Mon Jun  7 16:19:59 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Fri Apr 23 11:55:12 1999
+ * Modified at:   Mon May 31 21:55:42 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>,
X * Thomas Davis <rat...@radiks.net>
X  *     All Rights Reserved.
X  *     
@@ -209,8 +209,8 @@
X  *    Rushes through the state machine without any delay. If state == XMIT
X  *    then send queued data frames. 
X  */
-void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
-		     struct sk_buff *skb, struct irlap_info *info) 
+void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, 
+		    struct sk_buff *skb, struct irlap_info *info) 
X {
X 	int ret;
X 	
@@ -218,7 +218,7 @@
X 		return;
X 	
X   	DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n", 
-	      irlap_event[ event], irlap_state[ self->state]); 
+	      irlap_event[event], irlap_state[self->state]); 
X 	
X 	ret = (*state[ self->state]) (self, event, skb, info);
X 	
@@ -236,13 +236,12 @@
X 		if (skb_queue_len(&self->tx_list)) {
X 			/* Try to send away all queued data frames */
X 			while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
-				ret = (*state[ self->state])(self, SEND_I_CMD,
-							     skb, NULL);
+				ret = (*state[self->state])(self, SEND_I_CMD,
+							    skb, NULL);
X 				if ( ret == -EPROTO)
X 					break; /* Try again later! */
X 			}
X 		} else if (self->disconnect_pending) {
-			DEBUG(0, __FUNCTION__ "(), disconnecting!\n");
X 			self->disconnect_pending = FALSE;
X 			
X 			ret = (*state[self->state])(self, DISCONNECT_REQUEST,
@@ -274,22 +273,22 @@
X  *    Switches state and provides debug information
X  *
X  */
-void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) 
+void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) 
X {	
-	if ( !self || self->magic != LAP_MAGIC)
+	if (!self || self->magic != LAP_MAGIC)
X 		return;
X 	
-	DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]);
+	DEBUG(4, "next LAP state = %s\n", irlap_state[ state]);
X 
X 	self->state = state;
X 
X 	/*
X 	 *  If we are swithing away from a XMIT state then we are allowed to 
X 	 *  transmit a maximum number of bytes again when we enter the XMIT 
-	 *  state again. Since its possible to "switch" from XMIT to XMIT and
+	 *  state again. Since its possible to "switch" from XMIT to XMIT,
X 	 *  we cannot do this when swithing into the XMIT state :-)
X 	 */
-	if (( state != LAP_XMIT_P) && ( state != LAP_XMIT_S))
+	if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
X 		self->bytes_left = self->window_bytes;
X }
X 
@@ -310,7 +309,7 @@
X 	ASSERT( self != NULL, return -1;);
X 	ASSERT( self->magic == LAP_MAGIC, return -1;);
X 
-	switch( event) {
+	switch(event) {
X 	case CONNECT_REQUEST:
X 		ASSERT( self->irdev != NULL, return -1;);
X 
@@ -393,7 +392,6 @@
X 			irlap_start_query_timer( self, QUERY_TIMEOUT);
X 			irlap_next_state( self, LAP_REPLY);
X 		}
-
X 		dev_kfree_skb(skb);
X 		break;
X 
@@ -530,7 +528,7 @@
X 			irlap_send_discovery_xid_frame(self, info->S,
X 						       self->slot, FALSE,
X 						       discovery_rsp);
-
+			
X 			self->frame_sent = TRUE;
X 			irlap_next_state(self, LAP_REPLY);
X 		}
@@ -568,27 +566,28 @@
X 
X 	switch (event) {
X 	case CONNECT_RESPONSE:
-		skb_pull( skb, 11);
+		/* skb_pull(skb, 11); */
+		skb_pull(skb, sizeof(struct snrm_frame));
X 
-		ASSERT( self->irdev != NULL, return -1;);
-		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+		ASSERT(self->irdev != NULL, return -1;);
+		irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
X 
X 		irlap_initiate_connection_state( self);
X 
X 		/*
X 		 * We are allowed to send two frames!
X 		 */
-		irlap_send_ua_response_frame( self, &self->qos_rx);
-		irlap_send_ua_response_frame( self, &self->qos_rx);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
X 		
-		irlap_apply_connection_parameters( self, &self->qos_tx);
+		irlap_apply_connection_parameters(self, &self->qos_tx);
X 
X 		/*
X 		 *  The WD-timer could be set to the duration of the P-timer 
-		 *  for this case, but it is recommomended to use twice the 
+		 *  for this case, but it is recommended to use twice the 
X 		 *  value (note 3 IrLAP p. 60). 
X 		 */
-		irlap_start_wd_timer( self, self->wd_timeout);
+		irlap_start_wd_timer(self, self->wd_timeout);
X 		irlap_next_state( self, LAP_NRM_S);
X 		break;
X 
@@ -669,28 +668,30 @@
X 		 *  The device with the largest device address wins the battle
X 		 *  (both have sent a SNRM command!)
X 		 */
-		if ( info->daddr > self->saddr) {
-			del_timer( &self->final_timer);
-			irlap_initiate_connection_state( self);
+		if (info->daddr > self->saddr) {
+			del_timer(&self->final_timer);
+			irlap_initiate_connection_state(self);
X 
-			ASSERT( self->irdev != NULL, return -1;);
-			irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+			ASSERT(self->irdev != NULL, return -1;);
+			/* skb_pull(skb, 11); */
+			skb_pull(skb, sizeof(struct snrm_frame));
+			irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
X 			
X 			irlap_send_ua_response_frame(self, &self->qos_rx);
-			irlap_apply_connection_parameters( self, &self->qos_tx);
-			irlap_connect_confirm( self, skb);
+			irlap_apply_connection_parameters(self, &self->qos_tx);
+			irlap_connect_confirm(self, skb);
X 			
X 			/* 
X 			 *  The WD-timer could be set to the duration of the
-			 *  P-timer for this case, but it is recommomended
+			 *  P-timer for this case, but it is recommended
X 			 *  to use twice the value (note 3 IrLAP p. 60).  
X 			 */
-			irlap_start_wd_timer( self, self->wd_timeout);
+			irlap_start_wd_timer(self, self->wd_timeout);
X 			
-			irlap_next_state( self, LAP_NRM_S);
+			irlap_next_state(self, LAP_NRM_S);
X 		} else {
X 			/* We just ignore the other device! */
-			irlap_next_state( self, LAP_SETUP);
+			irlap_next_state(self, LAP_SETUP);
X 		}
X 		break;
X 	case RECV_UA_RSP:
@@ -702,9 +703,10 @@
X 
X 		/* Negotiate connection parameters */
X 		ASSERT( skb->len > 10, return -1;);
-		skb_pull( skb, 10);
+		/* skb_pull(skb, 10); */
+		skb_pull(skb, sizeof(struct ua_frame));
X 
-		ASSERT( self->irdev != NULL, return -1;);
+		ASSERT(self->irdev != NULL, return -1;);
X 		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
X 
X 		irlap_apply_connection_parameters( self, &self->qos_tx); 
@@ -758,36 +760,30 @@
X  *    stations.
X  * 
X  */
-static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
X {
X 	int ret = 0;
X 	
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
-
-	DEBUG( 4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", 
-	       irlap_event[ event], self->vs, self->vr); 
+	DEBUG(4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", 
+	      irlap_event[event], self->vs, self->vr);
X 		
X 	switch (event) {
X 	case SEND_I_CMD:
-		ASSERT( skb != NULL, return -1;);
-		DEBUG( 4, __FUNCTION__ "(), Window=%d\n", self->window);
-		
X 		/*
X 		 *  Only send frame if send-window > 0.
X 		 */ 
-		if (( self->window > 0) && ( !self->remote_busy)) {
+		if ((self->window > 0) && (!self->remote_busy)) {
X 
X 			/*
X 			 *  Test if we have transmitted more bytes over the 
X 			 *  link than its possible to do with the current 
X 			 *  speed and turn-around-time.
X 			 */
-			if (( skb->len+self->bofs_count) > self->bytes_left) {
-				DEBUG( 4, __FUNCTION__ "(), Not allowed to "
-				       "transmit more bytes!\n");
-				skb_queue_head( &self->tx_list, skb);
+			if ((skb->len+self->bofs_count) > self->bytes_left) {
+				DEBUG(4, __FUNCTION__ "(), Not allowed to "
+				      "transmit more bytes!\n");
+				skb_queue_head(&self->tx_list, skb);
X 
X 				/*
X 				 *  We should switch state to LAP_NRM_P, but
@@ -799,7 +795,7 @@
X 				 */
X 				return -EPROTO;
X 			}
-			self->bytes_left -= ( skb->len + self->bofs_count);
+			self->bytes_left -= (skb->len + self->bofs_count);
X 
X 			/*
X 			 *  Send data with poll bit cleared only if window > 1
@@ -808,11 +804,9 @@
X 			if (( self->window > 1) && 
X 			    skb_queue_len( &self->tx_list) > 0) 
X 			{   
-				DEBUG( 4, __FUNCTION__ "(), window > 1\n");
X 				irlap_send_data_primary( self, skb);
X 				irlap_next_state( self, LAP_XMIT_P);
X 			} else {
-				DEBUG( 4, __FUNCTION__ "(), window <= 1\n");
X 				irlap_send_data_primary_poll( self, skb);
X 				irlap_next_state( self, LAP_NRM_P);
X 				
@@ -930,9 +924,6 @@
X 	int ns_status;
X 	int nr_status;
X 
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == LAP_MAGIC, return -1;);
-
X 	switch (event) {
X 	case RECV_I_RSP: /* Optimize for the common case */
X 		/* FIXME: must check for remote_busy below */
@@ -944,7 +935,6 @@
X 		 */
X 		self->fast_RR = FALSE;
X #endif
-
X 		ASSERT( info != NULL, return -1;);
X 
X 		ns_status = irlap_validate_ns_received(self, info->ns);
@@ -1138,13 +1128,6 @@
X 		}
X 		break;
X 	case RECV_RR_RSP:
-		DEBUG(4, __FUNCTION__ "(), RECV_RR_FRAME: "
-		      "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n",
-		      self->retry_count, info->nr, self->va, self->vs, 
-		      self->vr);
-
-		ASSERT(info != NULL, return -1;);
-
X 		/*  
X 		 *  If you get a RR, the remote isn't busy anymore, 
X 		 *  no matter what the NR 
@@ -1191,14 +1174,6 @@
X 			/* Resend rejected frames */
X 			irlap_resend_rejected_frames( self, CMD_FRAME);
X 			
-			/*
-			 *  Start only if not running, DB
-			 *  TODO: Should this one be here?
-			 */
-			/* if ( !self->final_timer.prev) */
-/* 				irda_start_timer( FINAL_TIMER, self->final_timeout);  */
-
-			/* Keep state */
X 			irlap_next_state( self, LAP_NRM_P);
X 		} else if (ret == NR_INVALID) {
X 			DEBUG(1, "irlap_state_nrm_p: received RR with "
@@ -1207,8 +1182,7 @@
X 
X 			irlap_next_state( self, LAP_RESET_WAIT);
X 
-			irlap_disconnect_indication( self, 
-						     LAP_RESET_INDICATION);
+			irlap_disconnect_indication(self, LAP_RESET_INDICATION);
X 			self->xmitflag = TRUE;
X 		}
X 		if (skb)
@@ -1476,13 +1450,13 @@
X 		/*
X 		 *  Send frame only if send window > 1
X 		 */ 
-		if (( self->window > 0) && ( !self->remote_busy)) {
+		if ((self->window > 0) && ( !self->remote_busy)) {
X 			/*
X 			 *  Test if we have transmitted more bytes over the 
X 			 *  link than its possible to do with the current 
X 			 *  speed and turn-around-time.
X 			 */
-			if (( skb->len+self->bofs_count) > self->bytes_left) {
+			if ((skb->len+self->bofs_count) > self->bytes_left) {
X 				DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n");
X 				skb_queue_head( &self->tx_list, skb);
X 				/*
@@ -1504,11 +1478,9 @@
X 			if (( self->window > 1) && 
X 			    skb_queue_len( &self->tx_list) > 0) 
X 			{   
-				DEBUG( 4, __FUNCTION__ "(), window > 1\n");
X 				irlap_send_data_secondary( self, skb);
X 				irlap_next_state( self, LAP_XMIT_S);
X 			} else {
-				DEBUG( 4, "(), window <= 1\n");
X 				irlap_send_data_secondary_final( self, skb);
X 				irlap_next_state( self, LAP_NRM_S);
X 
@@ -1570,7 +1542,7 @@
X 			/* 
X 			 *  poll bit cleared?
X 			 */
-			if ( !info->pf) {
+			if (!info->pf) {
X 				self->vr = (self->vr + 1) % 8;
X 				
X 				/* Update Nr received */
@@ -1600,35 +1572,39 @@
X 				 *  also before changing to XMIT_S
X 				 *  state. (note 1, IrLAP p. 82) 
X 				 */
-				irlap_wait_min_turn_around( self, &self->qos_tx);
-				/*
-				 *  Any pending data requests?
+				irlap_wait_min_turn_around(self, &self->qos_tx);
+
+				/*  
+				 * Give higher layers a chance to
+				 * immediately reply with some data before
+				 * we decide if we should send a RR frame
+				 * or not
X 				 */
-				if (( skb_queue_len( &self->tx_list) > 0) && 
-				    ( self->window > 0)) 
+				irlap_data_indication(self, skb);
+
+				/* Any pending data requests?  */
+				if ((skb_queue_len(&self->tx_list) > 0) && 
+				    (self->window > 0)) 
X 				{
X 					self->ack_required = TRUE;
X 					
-					del_timer( &self->wd_timer);
+					del_timer(&self->wd_timer);
X 					
-					irlap_next_state( self, LAP_XMIT_S);
+					irlap_next_state(self, LAP_XMIT_S);
X 				} else {
-					irlap_send_rr_frame( self, RSP_FRAME);
-					irlap_start_wd_timer( self, self->wd_timeout);
+					irlap_send_rr_frame(self, RSP_FRAME);
+					irlap_start_wd_timer(self, self->wd_timeout);
X 
X 					/* Keep the state */
-					irlap_next_state( self, LAP_NRM_S);
+					irlap_next_state(self, LAP_NRM_S);
X 				}
-				irlap_data_indication( self, skb);
-
X 				break;
X 			}
X 		}
X 		/*
X 		 *  Check for Unexpected next to send (Ns)
X 		 */
-		if (( ns_status == NS_UNEXPECTED) && 
-		    ( nr_status == NR_EXPECTED)) 
+		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
X 		{
X 			/* Unexpected next to send, with final bit cleared */
X 			if ( !info->pf) {
@@ -1651,8 +1627,7 @@
X 		/* 
X 		 *  Unexpected Next to Receive(NR) ?
X 		 */
-		if (( ns_status == NS_EXPECTED) && 
-		    ( nr_status == NR_UNEXPECTED))
+		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
X 		{
X 			if ( info->pf) {
X 				DEBUG( 4, "RECV_I_RSP: frame(s) lost\n");
@@ -1748,20 +1723,20 @@
X 				irlap_update_nr_received( self, info->nr);
X 				del_timer( &self->wd_timer);
X 				
-				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
X 				irlap_next_state( self, LAP_XMIT_S);
X 			} else {			
X 				self->remote_busy = FALSE;
X 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
-				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_update_nr_received(self, info->nr);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
X 				
-				irlap_send_rr_frame( self, RSP_FRAME);
+				irlap_send_rr_frame(self, RSP_FRAME);
X 				
-				irlap_start_wd_timer( self, self->wd_timeout);
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_start_wd_timer(self, self->wd_timeout);
+				irlap_next_state(self, LAP_NRM_S);
X 			}
-		} else if ( nr_status == NR_UNEXPECTED) {
+		} else if (nr_status == NR_UNEXPECTED) {
X 			self->remote_busy = FALSE;
X 			irlap_update_nr_received( self, info->nr);
X 			irlap_resend_rejected_frames( self, RSP_FRAME);
@@ -1773,8 +1748,8 @@
X 		} else {
X 			DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
X 		} 
-		if ( skb)
-			dev_kfree_skb( skb);
+		if (skb)
+			dev_kfree_skb(skb);
X 
X 		break;
X 	case RECV_SNRM_CMD:
@@ -1886,7 +1861,7 @@
X 	ASSERT( self != NULL, return -ENODEV;);
X 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
X 	
-	switch( event) {
+	switch(event) {
X 	case RESET_RESPONSE:
X 		irlap_send_ua_response_frame( self, &self->qos_rx);
X 		irlap_initiate_connection_state( self);
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.2.9/linux/net/irda/irlap_frame.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irlap_frame.c	Mon Jun  7 16:19:59 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Fri Apr 23 09:30:42 1999
+ * Modified at:   Mon May 31 09:29:13 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, All Rights Resrved.
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, All Rights Resrved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -1001,10 +1001,6 @@
X {
X 	__u8  *frame;
X 	
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-
X 	frame = skb->data;
X 	
X 	/* Insert connection address */
@@ -1014,15 +1010,6 @@
X 	/* Insert next to receive (Vr) */
X 	frame[1] |= (self->vr << 5);  /* insert nr */
X 
-#if 0
-	{
-		int ns;
-		ns = (frame[1] >> 1) & 0x07; /* Next to send */
-
-		DEBUG(0, __FUNCTION__ "(), ns=%d\n", ns);
-	}
-#endif
-
X 	irlap_queue_xmit(self, skb);
X }
X 
@@ -1056,8 +1043,8 @@
X  *    Receive and parse an Unnumbered Information (UI) frame
X  *
X  */
-static void irlap_recv_ui_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				 struct irlap_info *info)
+static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				struct irlap_info *info)
X {
X 	__u8 *frame;
X 
@@ -1240,7 +1227,7 @@
X 	 *  Optimize for the common case and check if the frame is an
X 	 *  I(nformation) frame. Only I-frames have bit 0 set to 0
X 	 */
-	if(~control & 0x01) {
+	if (~control & 0x01) {
X 		irlap_recv_i_frame(self, skb, &info, command);
X 		self->stats.rx_packets++;
X 		return 0;
@@ -1254,7 +1241,7 @@
X 		 *  Received S(upervisory) frame, check which frame type it is
X 		 *  only the first nibble is of interest
X 		 */
-		switch(control & 0x0f) {
+		switch (control & 0x0f) {
X 		case RR:
X 			irlap_recv_rr_frame( self, skb, &info, command);
X 			self->stats.rx_packets++;
@@ -1279,7 +1266,7 @@
X 	/* 
X 	 *  This must be a C(ontrol) frame 
X 	 */
-	switch(control) {
+	switch (control) {
X 	case XID_RSP:
X 		irlap_recv_discovery_xid_rsp(self, skb, &info);
X 		break;
diff -u --recursive --new-file v2.2.9/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.2.9/linux/net/irda/irlmp.c	Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irlmp.c	Mon Jun  7 16:19:59 1999
@@ -6,10 +6,10 @@
X  * Status:        Stable.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Fri Apr 23 09:13:24 1999
+ * Modified at:   Mon May 31 21:49:41 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, 
X  *     All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
@@ -197,7 +197,7 @@
X }
X 
X /*
- * Function irlmp_close_lsap (self)
+ * Function __irlmp_close_lsap (self)
X  *
X  *    Remove an instance of LSAP
X  */
@@ -369,11 +369,11 @@
X 		if (!skb)
X 			return -ENOMEM;
X 
-		skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(skb, LMP_MAX_HEADER);
X 	} else
X 		skb = userdata;
X 	
-	/* Make room for MUX control header ( 3 bytes) */
+	/* Make room for MUX control header (3 bytes) */
X 	ASSERT(skb_headroom(skb) >= LMP_CONTROL_HEADER, return -1;);
X 	skb_push(skb, LMP_CONTROL_HEADER);
X 
@@ -443,25 +443,35 @@
X void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb) 
X {
X 	int max_seg_size;
-
-	DEBUG(3, __FUNCTION__ "()\n");
+	int lap_header_size;
+	int max_header_size;
X 	
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
X 	ASSERT(skb != NULL, return;);
X 	ASSERT(self->lap != NULL, return;);
X 
+	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	      self->slsap_sel, self->dlsap_sel);
+
X 	self->qos = *self->lap->qos;
X 
-	max_seg_size = self->lap->qos->data_size.value;
-	DEBUG(4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
+	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
X 	
+	lap_header_size = irlap_get_header_size(self->lap->irlap);
+
+	max_header_size = LMP_HEADER + lap_header_size;
+
+	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+
X 	/* Hide LMP_CONTROL_HEADER header from layer above */
X 	skb_pull(skb, LMP_CONTROL_HEADER);
X 
X 	if (self->notify.connect_indication)
X 		self->notify.connect_indication(self->notify.instance, self, 
-						&self->qos, max_seg_size, skb);
+						&self->qos, max_seg_size, 
+						max_header_size, skb);
X }
X 
X /*
@@ -470,24 +480,22 @@
X  *    Service user is accepting connection
X  *
X  */
-void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) 
+void irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 
X {
-	DEBUG(3, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( userdata != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(userdata != NULL, return;);
X 
X 	self->connected = TRUE;
X 
-	DEBUG( 4, "irlmp_connect_response: slsap_sel=%02x, dlsap_sel=%02x\n", 
-	       self->slsap_sel, self->dlsap_sel);
+	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	      self->slsap_sel, self->dlsap_sel);
X 
X 	/* Make room for MUX control header ( 3 bytes) */
-	ASSERT( skb_headroom( userdata) >= LMP_CONTROL_HEADER, return;);
-	skb_push( userdata, LMP_CONTROL_HEADER);
+	ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return;);
+	skb_push(userdata, LMP_CONTROL_HEADER);
X 	
-	irlmp_do_lsap_event( self, LM_CONNECT_RESPONSE, userdata);
+	irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
X }
X 
X /*
@@ -498,25 +506,34 @@
X void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) 
X {
X 	int max_seg_size;
+	int max_header_size;
+	int lap_header_size;
X 
X 	DEBUG(3, __FUNCTION__ "()\n");
X 	
-	ASSERT( skb != NULL, return;);
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
X 	
-	ASSERT( self->lap != NULL, return;);
+	ASSERT(self->lap != NULL, return;);
X 	self->qos = *self->lap->qos;
X 
-	max_seg_size = self->qos.data_size.value;
-	DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
+	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+
+	lap_header_size = irlap_get_header_size(self->lap->irlap);
X 	
+	max_header_size = LMP_HEADER + lap_header_size;
+
+	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+
X 	/* Hide LMP_CONTROL_HEADER header from layer above */
-	skb_pull( skb, LMP_CONTROL_HEADER);
+	skb_pull(skb, LMP_CONTROL_HEADER);
X 
-	if ( self->notify.connect_confirm) {
-		self->notify.connect_confirm( self->notify.instance, self,
-					      &self->qos, max_seg_size, skb);
+	if (self->notify.connect_confirm) {
+		self->notify.connect_confirm(self->notify.instance, self,
+					     &self->qos, max_seg_size, 
+					     max_header_size, skb);
X 	}
X }
X 
@@ -620,8 +637,8 @@
X  *
X  *    LSAP is being closed!
X  */
-void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, 
-				  struct sk_buff *userdata) 
+void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, 
+				 struct sk_buff *userdata) 
X {
X 	struct lsap_cb *lsap;
X 
@@ -637,6 +654,10 @@
X 	self->connected = FALSE;
X 	self->dlsap_sel = LSAP_ANY;
X 
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+	irlmp->cache.valid = FALSE;
+#endif
+
X 	/* 
X 	 *  Remove association between this LSAP and the link it used 
X 	 */
@@ -975,7 +996,7 @@
X 	DEBUG( 1, "irlmp_status_request(), Not implemented\n");
X }
X 
-void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) 
+void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) 
X {
X 	DEBUG( 4, "irlmp_status_indication(), Not implemented\n");
X }
@@ -1418,14 +1439,14 @@
X  *    Give some info to the /proc file system
X  *
X  */
-int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused)
+int irlmp_proc_read(char *buf, char **start, off_t offset, int len, 
+		    int unused)
X {
X 	struct lsap_cb *self;
X 	struct lap_cb *lap;
X 	unsigned long flags;
X 
-	ASSERT( irlmp != NULL, return 0;);
+	ASSERT(irlmp != NULL, return 0;);
X 	
X 	save_flags( flags);
X 	cli();
@@ -1449,35 +1470,34 @@
X  	} 
X 
X 	len += sprintf( buf+len, "\nRegistred Link Layers:\n");
-	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
-	while ( lap != NULL) {
-		ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;);
X 
-		len += sprintf( buf+len, "lap state: %s, ", 
-				irlmp_state[ lap->lap_state]);
+	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
+	while (lap != NULL) {
+		len += sprintf(buf+len, "lap state: %s, ", 
+			       irlmp_state[lap->lap_state]);
SHAR_EOF
true || echo 'restore of patch-2.2.10 failed'
fi
echo 'End of  part 21'
echo 'File patch-2.2.10 is continued in part 22'
echo 22 > _shar_seq_.tmp
exit 0