lines    added  deleted
linux/CREDITS                               :      23        3        6
linux/Documentation/Configure.help          :     128      108        0
linux/Documentation/filesystems/isofs.txt   :       5        2        0
linux/Documentation/isdn/HiSax.cert         :      76       76        0
linux/Documentation/isdn/INTERFACE          :      31       12        2
linux/Documentation/isdn/README             :     426      102       82
linux/Documentation/isdn/README.HiSax       :     355      112       60
linux/Documentation/isdn/README.act2000     :      14        2        2
linux/Documentation/isdn/README.audio       :      39       10        8
linux/Documentation/isdn/README.concap      :       4        1        0
linux/Documentation/isdn/README.eicon       :      92       92        0
linux/Documentation/isdn/README.icn         :       5        1        1
linux/Documentation/isdn/README.x25         :     266       69      116
linux/Documentation/networking/decnet.txt   :     146      146        0
linux/Documentation/sound/CMI8330           :     104       33       21
linux/Documentation/sound/CMI8338           :      32       32        0
linux/Makefile                              :       7        1        1
linux/README                                :      31        4        4
linux/arch/alpha/kernel/process.c           :      12        2        2
linux/arch/alpha/kernel/ptrace.c            :       9        2        1
linux/arch/arm/kernel/ptrace.c              :       7        1        0
linux/arch/i386/defconfig                   :      10        2        0
linux/arch/mips/kernel/ptrace.c             :       7        1        0
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            :      23        8        2
linux/arch/ppc/coffboot/Makefile            :      18        8        2
linux/arch/ppc/common_defconfig             :     207       30       52
linux/arch/ppc/config.in                    :      28        8        3
linux/arch/ppc/defconfig                    :     207       30       52
linux/arch/ppc/kernel/Makefile              :       8        1        1
linux/arch/ppc/kernel/chrp_pci.c            :       7        1        0
linux/arch/ppc/kernel/chrp_setup.c          :      29        0       23
linux/arch/ppc/kernel/head.S                :     215       89       12
linux/arch/ppc/kernel/mbx_setup.c           :       6        1        1
linux/arch/ppc/kernel/misc.S                :      15        0        9
linux/arch/ppc/kernel/pmac_setup.c          :      29        5        3
linux/arch/ppc/kernel/prep_pci.c            :      24        5        1
linux/arch/ppc/kernel/prep_setup.c          :      29        4        5
linux/arch/ppc/kernel/process.c             :      42        3       21
linux/arch/ppc/kernel/ptrace.c              :      13        5        1
linux/arch/ppc/kernel/residual.c            :       6        1        1
linux/arch/ppc/kernel/setup.c               :       6        1        1
linux/arch/ppc/kernel/softemu8xx.c          :      20        7        0
linux/arch/ppc/kernel/syscalls.c            :      16        1        4
linux/arch/ppc/kernel/traps.c               :      23        0        3
linux/arch/ppc/mm/fault.c                   :      15        0        2
linux/arch/ppc/mm/init.c                    :      15        2        2
linux/arch/ppc/xmon/Makefile                :       6        6        0
linux/arch/ppc/xmon/adb.c                   :     212      212        0
linux/arch/ppc/xmon/ansidecl.h              :     141      141        0
linux/arch/ppc/xmon/nonstdio.h              :      22       22        0
linux/arch/ppc/xmon/ppc-dis.c               :     190      190        0
linux/arch/ppc/xmon/ppc-opc.c               :    2816     2816        0
linux/arch/ppc/xmon/ppc.h                   :     240      240        0
linux/arch/ppc/xmon/privinst.h              :      73       73        0
linux/arch/ppc/xmon/setjmp.c                :      29       29        0
linux/arch/ppc/xmon/start.c                 :     298      298        0
linux/arch/ppc/xmon/subr_prf.c              :      47       47        0
linux/arch/ppc/xmon/xmon.c                  :    1323     1323        0
linux/arch/sparc/defconfig                  :      26        6        0
linux/arch/sparc/kernel/irq.c               :      32        3        5
linux/arch/sparc/kernel/ptrace.c            :       7        1        0
linux/arch/sparc/kernel/setup.c             :      13        2        1
linux/arch/sparc/kernel/sys_sunos.c         :      14        2        2
linux/arch/sparc/math-emu/Makefile          :      16        3        3
linux/arch/sparc/math-emu/fabss.c           :      13        7        1
linux/arch/sparc/math-emu/fcmpd.c           :      42       24        9
linux/arch/sparc/math-emu/fcmped.c          :      42       24        9
linux/arch/sparc/math-emu/fcmpeq.c          :      40       22        7
linux/arch/sparc/math-emu/fcmpes.c          :      42       24        9
linux/arch/sparc/math-emu/fcmpq.c           :      40       22        7
linux/arch/sparc/math-emu/fcmps.c           :      42       24        9
linux/arch/sparc/math-emu/fdmulq.c          :      29       14        3
linux/arch/sparc/math-emu/fdtoq.c           :      25       13        2
linux/arch/sparc/math-emu/fdtos.c           :      25       13        2
linux/arch/sparc/math-emu/fmovs.c           :      10        7        0
linux/arch/sparc/math-emu/fnegs.c           :      10        7        0
linux/arch/sparc/math-emu/fqtod.c           :      25       13        2
linux/arch/sparc/math-emu/fqtos.c           :      25       13        2
linux/arch/sparc/math-emu/fsmuld.c          :      29       14        3
linux/arch/sparc/math-emu/fstod.c           :      25       13        2
linux/arch/sparc/math-emu/fstoq.c           :      25       13        2
linux/arch/sparc/math-emu/math.c            :     659      235      324
linux/arch/sparc/math-emu/sfp-machine.h     :     545      156      350
linux/arch/sparc/math-emu/sfp-util.h        :     115      115        0
linux/arch/sparc64/defconfig                :      26        6        0
linux/arch/sparc64/kernel/etrap.S           :      34        4        6
linux/arch/sparc64/kernel/head.S            :      13        2        1
linux/arch/sparc64/kernel/process.c         :       5        1        1
linux/arch/sparc64/kernel/ptrace.c          :       7        1        0
linux/arch/sparc64/kernel/rtrap.S           :      13        1        2
linux/arch/sparc64/kernel/setup.c           :      15        3        1
linux/arch/sparc64/kernel/smp.c             :      35       10        9
linux/arch/sparc64/kernel/sys_sunos32.c     :      14        2        2
linux/arch/sparc64/kernel/trampoline.S      :      14        3        1
linux/arch/sparc64/kernel/traps.c           :      76       30        7
linux/arch/sparc64/kernel/unaligned.c       :      44        8        5
linux/arch/sparc64/lib/VIS.h                :      51       19        4
linux/arch/sparc64/lib/VISbzero.S           :      72       21        7
linux/arch/sparc64/lib/VIScopy.S            :     219       73       32
linux/arch/sparc64/lib/VIScsum.S            :      27        6        1
linux/arch/sparc64/lib/VIScsumcopy.S        :      77       20       10
linux/arch/sparc64/lib/VISmemset.S          :      23        4        2
linux/arch/sparc64/lib/blockops.S           :      21        3        1
linux/arch/sparc64/lib/checksum.S           :      20        3        0
linux/arch/sparc64/lib/strlen_user.S        :      40        6        6
linux/arch/sparc64/lib/strncpy_from_user.S  :     100       28       26
linux/arch/sparc64/math-emu/Makefile        :       8        1        1
linux/arch/sparc64/math-emu/double.h        :     161       87       19
linux/arch/sparc64/math-emu/extended.h      :     388      388        0
linux/arch/sparc64/math-emu/fabsq.c         :      10        7        0
linux/arch/sparc64/math-emu/faddd.c         :      26       14        3
linux/arch/sparc64/math-emu/faddq.c         :      26       14        3
linux/arch/sparc64/math-emu/fadds.c         :      26       14        3
linux/arch/sparc64/math-emu/fcmpeq.c        :      52       27       13
linux/arch/sparc64/math-emu/fcmpq.c         :      52       27       13
linux/arch/sparc64/math-emu/fdivd.c         :      33       14       10
linux/arch/sparc64/math-emu/fdivq.c         :      33       14       10
linux/arch/sparc64/math-emu/fdivs.c         :      34       14       10
linux/arch/sparc64/math-emu/fdmulq.c        :      29       14        3
linux/arch/sparc64/math-emu/fdtoi.c         :      30       17        5
linux/arch/sparc64/math-emu/fdtoq.c         :      25       13        2
linux/arch/sparc64/math-emu/fdtos.c         :      25       13        2
linux/arch/sparc64/math-emu/fdtox.c         :      30       17        5
linux/arch/sparc64/math-emu/fitoq.c         :      23       12        1
linux/arch/sparc64/math-emu/fmovq.c         :      10        7        0
linux/arch/sparc64/math-emu/fmuld.c         :      26       14        3
linux/arch/sparc64/math-emu/fmulq.c         :      26       14        3
linux/arch/sparc64/math-emu/fmuls.c         :      26       14        3
linux/arch/sparc64/math-emu/fnegq.c         :      14        7        1
linux/arch/sparc64/math-emu/fqtod.c         :      25       13        2
linux/arch/sparc64/math-emu/fqtoi.c         :      30       17        5
linux/arch/sparc64/math-emu/fqtos.c         :      25       13        2
linux/arch/sparc64/math-emu/fqtox.c         :      30       17        5
linux/arch/sparc64/math-emu/fsmuld.c        :      29       14        3
linux/arch/sparc64/math-emu/fsqrtd.c        :      24       13        2
linux/arch/sparc64/math-emu/fsqrtq.c        :      24       13        2
linux/arch/sparc64/math-emu/fsqrts.c        :      24       13        2
linux/arch/sparc64/math-emu/fstod.c         :      25       13        2
linux/arch/sparc64/math-emu/fstoi.c         :      30       17        5
linux/arch/sparc64/math-emu/fstoq.c         :      25       13        2
linux/arch/sparc64/math-emu/fstox.c         :      30       17        5
linux/arch/sparc64/math-emu/fsubd.c         :      28       14        3
linux/arch/sparc64/math-emu/fsubq.c         :      28       14        3
linux/arch/sparc64/math-emu/fsubs.c         :      28       14        3
linux/arch/sparc64/math-emu/fxtoq.c         :      23       12        1
linux/arch/sparc64/math-emu/math.c          :      88       19       28
linux/arch/sparc64/math-emu/op-1.h          :     116       58        6
linux/arch/sparc64/math-emu/op-2.h          :     519      214      134
linux/arch/sparc64/math-emu/op-4.h          :     799      527      163
linux/arch/sparc64/math-emu/op-8.h          :     103      103        0
linux/arch/sparc64/math-emu/op-common.h     :     410      133       66
linux/arch/sparc64/math-emu/quad.h          :     168       86       19
linux/arch/sparc64/math-emu/sfp-machine.h   :     282       46      203
linux/arch/sparc64/math-emu/sfp-util.h      :     120      120        0
linux/arch/sparc64/math-emu/single.h        :      91       55       11
linux/arch/sparc64/math-emu/soft-fp.h       :     177      103       21
linux/arch/sparc64/math-emu/udivmodti4.c    :     191        0      191
linux/arch/sparc64/mm/init.c                :      23        5        1
linux/arch/sparc64/solaris/ioctl.c          :      16        4        1
linux/drivers/block/Makefile                :      12        2        2
linux/drivers/block/aec6210.c               :       7        0        1
linux/drivers/block/alim15x3.c              :       7        1        0
linux/drivers/block/blkpg.c                 :      12        2        0
linux/drivers/block/cmd646.c                :      21        7        5
linux/drivers/block/cy82c693.c              :       8        1        1
linux/drivers/block/hpt343.c                :       7        0        1
linux/drivers/block/ide-cd.c                :      15        2        0
linux/drivers/block/ide-disk.c              :      50        8       18
linux/drivers/block/ide-probe.c             :      13        4        3
linux/drivers/block/ide.c                   :      92       25       11
linux/drivers/block/loop.c                  :       8        2        0
linux/drivers/block/ns87415.c               :      25       17        0
linux/drivers/block/paride/paride.c         :      17        2        2
linux/drivers/block/pdc202xx.c              :       7        0        1
linux/drivers/block/pdc4030.c               :     265      123       34
linux/drivers/block/via82c586.c             :       7        1        0
linux/drivers/cdrom/sonycd535.c             :       8        1        1
linux/drivers/char/Config.in                :       7        1        0
linux/drivers/char/Makefile                 :      16       10        0
linux/drivers/char/bttv.c                   :      60       40        0
linux/drivers/char/bttv.h                   :      21        9        0
linux/drivers/char/cyclades.c               :     775      211      152
linux/drivers/char/i2c-parport.c            :     149      149        0
linux/drivers/char/keyboard.c               :      20        3        3
linux/drivers/char/stallion.c               :       8        1        1
linux/drivers/isdn/Config.in                :      44       10        5
linux/drivers/isdn/Makefile                 :      32       12        1
linux/drivers/isdn/act2000/act2000.h        :      32        8        4
linux/drivers/isdn/act2000/act2000_isa.c    :      28       13        2
linux/drivers/isdn/act2000/act2000_isa.h    :      20        5        2
linux/drivers/isdn/act2000/capi.c           :      21        5        2
linux/drivers/isdn/act2000/capi.h           :      20        5        2
linux/drivers/isdn/act2000/module.c         :     105       20       14
linux/drivers/isdn/avmb1/b1capi.c           :     384      155       29
linux/drivers/isdn/avmb1/b1lli.c            :     705      377       52
linux/drivers/isdn/avmb1/b1pci.c            :      55       22        4
linux/drivers/isdn/avmb1/capi.c             :      70       29        2
linux/drivers/isdn/avmb1/capidev.h          :      11        4        0
linux/drivers/isdn/avmb1/capidrv.c          :     863      234      148
linux/drivers/isdn/avmb1/capidrv.h          :     106       60       13
linux/drivers/isdn/avmb1/compat.h           :      23        5        1
linux/drivers/isdn/eicon/Makefile           :      13       13        0
linux/drivers/isdn/eicon/eicon.h            :     528      528        0
linux/drivers/isdn/eicon/eicon_dsp.h        :     304      304        0
linux/drivers/isdn/eicon/eicon_idi.c        :    1479     1479        0
linux/drivers/isdn/eicon/eicon_idi.h        :     248      248        0
linux/drivers/isdn/eicon/eicon_io.c         :     755      755        0
linux/drivers/isdn/eicon/eicon_isa.c        :     432      432        0
linux/drivers/isdn/eicon/eicon_isa.h        :     144      144        0
linux/drivers/isdn/eicon/eicon_mod.c        :    1210     1210        0
linux/drivers/isdn/eicon/eicon_pci.c        :     952      952        0
linux/drivers/isdn/eicon/eicon_pci.h        :     188      188        0
linux/drivers/isdn/hisax/Makefile           :     107       42        6
linux/drivers/isdn/hisax/arcofi.c           :      83       39       10
linux/drivers/isdn/hisax/arcofi.h           :      25        9        2
linux/drivers/isdn/hisax/asuscom.c          :     271      147       33
linux/drivers/isdn/hisax/avm_a1.c           :      75       18       13
linux/drivers/isdn/hisax/avm_a1p.c          :     334      334        0
linux/drivers/isdn/hisax/avm_pci.c          :     865      865        0
linux/drivers/isdn/hisax/callc.c            :    2275      638      788
linux/drivers/isdn/hisax/cert.c             :      55       55        0
linux/drivers/isdn/hisax/config.c           :    1311      971       67
linux/drivers/isdn/hisax/diva.c             :     515      224       92
linux/drivers/isdn/hisax/elsa.c             :     700      279      144
linux/drivers/isdn/hisax/elsa_ser.c         :     749      749        0
linux/drivers/isdn/hisax/fsm.c              :     204       42       73
linux/drivers/isdn/hisax/hfc_2bds0.c        :     778      139      215
linux/drivers/isdn/hisax/hfc_2bs0.c         :     369       80       98
linux/drivers/isdn/hisax/hisax.h            :     866      312      196
linux/drivers/isdn/hisax/hscx.c             :     348      125       80
linux/drivers/isdn/hisax/hscx.h             :      20        5        1
linux/drivers/isdn/hisax/hscx_irq.c         :     263       62       70
linux/drivers/isdn/hisax/ipac.h             :      23        5        1
linux/drivers/isdn/hisax/isac.c             :     586      152      155
linux/drivers/isdn/hisax/isac.h             :      45       10        2
linux/drivers/isdn/hisax/isar.c             :     937      937        0
linux/drivers/isdn/hisax/isar.h             :      91       91        0
linux/drivers/isdn/hisax/isdnl1.c           :    1420      298      796
linux/drivers/isdn/hisax/isdnl1.h           :      55       15       19
linux/drivers/isdn/hisax/isdnl2.c           :    1052      280      192
linux/drivers/isdn/hisax/isdnl3.c           :     305      222       22
linux/drivers/isdn/hisax/isdnl3.h           :      38       16        3
linux/drivers/isdn/hisax/ix1_micro.c        :      36        6        6
linux/drivers/isdn/hisax/l3_1tr6.c          :     638      199      133
linux/drivers/isdn/hisax/l3_1tr6.h          :      20        5        1
linux/drivers/isdn/hisax/l3dss1.c           :    1960      813      526
linux/drivers/isdn/hisax/l3dss1.h           :      24        7        2
linux/drivers/isdn/hisax/lmgr.c             :      56       19       11
linux/drivers/isdn/hisax/md5sums.asc        :      29       29        0
linux/drivers/isdn/hisax/mic.c              :      36        6        6
linux/drivers/isdn/hisax/netjet.c           :     837      217      204
linux/drivers/isdn/hisax/niccy.c            :     230       77       44
linux/drivers/isdn/hisax/q931.c             :     261       94       40
linux/drivers/isdn/hisax/rawhdlc.c          :       5        1        1
linux/drivers/isdn/hisax/s0box.c            :     277      277        0
linux/drivers/isdn/hisax/sedlbauer.c        :     670      469       79
linux/drivers/isdn/hisax/sportster.c        :      42       10        6
linux/drivers/isdn/hisax/tei.c              :     387      108       98
linux/drivers/isdn/hisax/teleint.c          :     125       38       29
linux/drivers/isdn/hisax/teles0.c           :     113       23       18
linux/drivers/isdn/hisax/teles3.c           :     130       21       19
linux/drivers/isdn/hisax/teles3c.c          :      69       12       18
linux/drivers/isdn/hisax/telespci.c         :     371      371        0
linux/drivers/isdn/icn/icn.c                :     127       65        7
linux/drivers/isdn/icn/icn.h                :      11        2        2
linux/drivers/isdn/isdn_audio.c             :     140      103        4
linux/drivers/isdn/isdn_audio.h             :      42       16        2
linux/drivers/isdn/isdn_bsdcomp.c           :     934      934        0
linux/drivers/isdn/isdn_budget.c            :     206      206        0
linux/drivers/isdn/isdn_cards.c             :      43       15        2
linux/drivers/isdn/isdn_cards.h             :      20        5        2
linux/drivers/isdn/isdn_common.c            :    1155      453      304
linux/drivers/isdn/isdn_common.h            :      68       37        6
linux/drivers/isdn/isdn_concap.c            :      50       15        9
linux/drivers/isdn/isdn_net.c               :    1072      359      194
linux/drivers/isdn/isdn_net.h               :      40       14        2
linux/drivers/isdn/isdn_ppp.c               :    1586      949      143
linux/drivers/isdn/isdn_ppp.h               :      25        7        1
linux/drivers/isdn/isdn_tty.c               :    1097      562      117
linux/drivers/isdn/isdn_tty.h               :      48       22        2
linux/drivers/isdn/isdn_x25iface.c          :      37       18        2
linux/drivers/isdn/isdnloop/isdnloop.c      :      44       17        3
linux/drivers/isdn/isdnloop/isdnloop.h      :      15        4        1
linux/drivers/isdn/pcbit/callbacks.c        :      42       23        4
linux/drivers/isdn/pcbit/drv.c              :       9        3        0
linux/drivers/isdn/pcbit/pcbit.h            :      11        4        0
linux/drivers/isdn/sc/message.c             :       6        1        1
linux/drivers/misc/parport_init.c           :      28        5        1
linux/drivers/misc/parport_pc.c             :     133       86        4
linux/drivers/misc/parport_share.c          :     125       84       11
linux/drivers/net/Space.c                   :       4        1        0
linux/drivers/net/arcnet.c                  :      22        4        0
linux/drivers/net/cosa.c                    :      28        6        2
linux/drivers/net/eexpress.c                :      59       20        4
linux/drivers/net/hamradio/bpqether.c       :      18        7        2
linux/drivers/net/irda/Config.in            :      37       19       13
linux/drivers/net/irda/Makefile             :      44       24        0
linux/drivers/net/irda/actisys.c            :     266       56       91
linux/drivers/net/irda/esi.c                :     153       27       45
linux/drivers/net/irda/girbil.c             :     185       18       57
linux/drivers/net/irda/irport.c             :     418      299       42
linux/drivers/net/irda/irtty.c              :     270       43      124
linux/drivers/net/irda/litelink.c           :     209      209        0
linux/drivers/net/irda/pc87108.c            :     133       25       18
linux/drivers/net/irda/tekram.c             :     185       23       64
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      238
linux/drivers/net/lapbether.c               :      16        6        1
linux/drivers/net/net_init.c                :      65       15        3
linux/drivers/net/smc-ultra.c               :      10        1        1
linux/drivers/net/strip.c                   :      23        5        1
linux/drivers/net/sunhme.c                  :      24        5        5
linux/drivers/sbus/char/Config.in           :       5        1        0
linux/drivers/sbus/char/Makefile            :      14        8        0
linux/drivers/sbus/char/aurora.c            :    2373     2373        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/README.st                :      24        1       10
linux/drivers/scsi/scsi.c                   :      31       11        0
linux/drivers/scsi/st.c                     :      33        2        4
linux/drivers/scsi/st.h                     :       7        0        1
linux/drivers/sound/Config.in               :       7        1        0
linux/drivers/sound/Makefile                :       7        1        0
linux/drivers/sound/cmpci.c                 :    2391     2391        0
linux/drivers/sound/es1370.c                :     157       39       14
linux/drivers/sound/lowlevel/awe_wave.c     :      12        2        2
linux/drivers/sound/sb_common.c             :     101       38       15
linux/drivers/sound/sb_ess.c                :    1428      428      592
linux/drivers/sound/sound_core.c            :       9        3        0
linux/drivers/usb/Config.in                 :      46       16       15
linux/drivers/usb/Makefile                  :     176       87       49
linux/drivers/usb/acm.c                     :     184       96       23
linux/drivers/usb/audio.c                   :      25       15        0
linux/drivers/usb/cpia.c                    :      23       12        0
linux/drivers/usb/hub.c                     :      50       13        8
linux/drivers/usb/inits.h                   :      10        3        3
linux/drivers/usb/keyboard.c                :      33       17        2
linux/drivers/usb/keymap.c                  :      15        2        2
linux/drivers/usb/maps/fixup.map            :      16        1        2
linux/drivers/usb/mouse.c                   :      63       39        0
linux/drivers/usb/ohci-hcd.c                :     325       98       55
linux/drivers/usb/ohci-hcd.h                :       7        0        1
linux/drivers/usb/ohci.c                    :     252       50       43
linux/drivers/usb/ohci.h                    :       7        0        1
linux/drivers/usb/printer.c                 :     412      412        0
linux/drivers/usb/uhci-debug.c              :      74       24        7
linux/drivers/usb/uhci.c                    :     568      155       81
linux/drivers/usb/uhci.h                    :       8        0        2
linux/drivers/usb/usb-core.c                :      93       93        0
linux/drivers/usb/usb-debug.c               :       9        5        1
linux/drivers/usb/usb.c                     :     471      247       61
linux/drivers/usb/usb.h                     :     131       28        7
linux/drivers/video/cgsixfb.c               :      55       20        5
linux/drivers/video/vga16fb.c               :       7        0        1
linux/fs/Config.in                          :       7        1        0
linux/fs/binfmt_aout.c                      :      40       26        1
linux/fs/binfmt_elf.c                       :      18        6        6
linux/fs/block_dev.c                        :       8        2        0
linux/fs/efs/.cvsignore                     :       2        0        2
linux/fs/efs/super.c                        :      29        5        1
linux/fs/exec.c                             :      14        2        3
linux/fs/isofs/inode.c                      :     110       38        5
linux/fs/ncpfs/ioctl.c                      :       8        1        1
linux/fs/open.c                             :       8        1        1
linux/fs/select.c                           :      13        5        1
linux/fs/stat.c                             :      35        4        4
linux/include/asm-alpha/processor.h         :      12        6        0
linux/include/asm-alpha/semaphore.h         :     118       70        8
linux/include/asm-arm/processor.h           :      12        6        0
linux/include/asm-i386/processor.h          :      21        8        0
linux/include/asm-i386/softirq.h            :      23       10        0
linux/include/asm-i386/spinlock.h           :     135       29       58
linux/include/asm-i386/system.h             :      11        5        0
linux/include/asm-m68k/processor.h          :      12        6        0
linux/include/asm-mips/processor.h          :      12        6        0
linux/include/asm-ppc/ide.h                 :      54       20        7
linux/include/asm-ppc/mmu.h                 :      49       19        0
linux/include/asm-ppc/pgtable.h             :      11        5        0
linux/include/asm-ppc/processor.h           :      22       10        0
linux/include/asm-ppc/ptrace.h              :      43       21       14
linux/include/asm-ppc/semaphore.h           :      83       51       12
linux/include/asm-ppc/system.h              :       7        0        1
linux/include/asm-sparc/pgtable.h           :       5        1        1
linux/include/asm-sparc/processor.h         :      18        7        1
linux/include/asm-sparc/softirq.h           :      29        8        1
linux/include/asm-sparc/spinlock.h          :      94       21        0
linux/include/asm-sparc64/asm_offsets.h     :    1011      334      340
linux/include/asm-sparc64/checksum.h        :      31        9        6
linux/include/asm-sparc64/fpumacro.h        :      44        0       40
linux/include/asm-sparc64/md.h              :      14        2        2
linux/include/asm-sparc64/mmu_context.h     :      68       15       17
linux/include/asm-sparc64/pgtable.h         :       5        1        1
linux/include/asm-sparc64/processor.h       :      93       25       19
linux/include/asm-sparc64/softirq.h         :      19        5        1
linux/include/asm-sparc64/spinlock.h        :     117       47        0
linux/include/asm-sparc64/uaccess.h         :     139       18       29
linux/include/linux/b1lli.h                 :     134       51       24
linux/include/linux/blkpg.h                 :       8        1        1
linux/include/linux/cyclades.h              :       9        2        1
linux/include/linux/dn.h                    :     161      161        0
linux/include/linux/i2c.h                   :      16        3        0
linux/include/linux/ide.h                   :      12        0        8
linux/include/linux/if_arp.h                :       7        1        0
linux/include/linux/interrupt.h             :       7        1        0
linux/include/linux/isdn.h                  :     553      234      143
linux/include/linux/isdn_budget.h           :      62       62        0
linux/include/linux/isdn_lzscomp.h          :      26       26        0
linux/include/linux/isdn_ppp.h              :     264      196       25
linux/include/linux/isdn_timru.h            :     119      119        0
linux/include/linux/isdnif.h                :     101       41        9
linux/include/linux/lp.h                    :      35       10        6
linux/include/linux/major.h                 :       8        2        0
linux/include/linux/netdevice.h             :      18        4        1
linux/include/linux/pagemap.h               :       8        1        1
linux/include/linux/parport.h               :      50       22        1
linux/include/linux/proc_fs.h               :      14        3        3
linux/include/linux/rtnetlink.h             :      20        6        1
linux/include/linux/sched.h                 :      32        7        3
linux/include/linux/skbuff.h                :     166       34       31
linux/include/linux/sysctl.h                :      49       35        7
linux/include/linux/wait.h                  :      33        6        4
linux/include/net/decnet_call.h             :       2        2        0
linux/include/net/dn.h                      :     206      206        0
linux/include/net/dn_dev.h                  :     194      194        0
linux/include/net/dn_fib.h                  :      83       83        0
linux/include/net/dn_neigh.h                :      29       29        0
linux/include/net/dn_nsp.h                  :     194      194        0
linux/include/net/dn_raw.h                  :      17       17        0
linux/include/net/dn_route.h                :      74       74        0
linux/include/net/dst.h                     :       9        0        3
linux/include/net/ip.h                      :       7        0        1
linux/include/net/ip_masq.h                 :      24        0       18
linux/include/net/irda/crc.h                :      34        9        6
linux/include/net/irda/dongle.h             :      31        5        3
linux/include/net/irda/ircomm_common.h      :      54        5        8
linux/include/net/irda/irda.h               :      34        6        4
linux/include/net/irda/irda_device.h        :     121       46       12
linux/include/net/irda/iriap.h              :      30        4        4
linux/include/net/irda/irlan_common.h       :     101       25       16
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             :      31        7        7
linux/include/net/irda/irttp.h              :      50        7        7
linux/include/net/irda/irtty.h              :      57        9       18
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/route.h                   :       8        0        2
linux/include/net/sock.h                    :     206       91       38
linux/include/net/tcp.h                     :      50        7        8
linux/kernel/fork.c                         :      11        4        1
linux/kernel/signal.c                       :      14        2        2
linux/kernel/time.c                         :      16        3        1
linux/mm/filemap.c                          :      20        2       11
linux/mm/memory.c                           :      23        7        9
linux/mm/mmap.c                             :       9        3        0
linux/mm/slab.c                             :       8        1        1
linux/mm/swapfile.c                         :      86       25        9
linux/net/Config.in                         :      14        4        4
linux/net/Makefile                          :       8        1        1
linux/net/core/datagram.c                   :      18        3        3
linux/net/core/dev.c                        :     383       82       43
linux/net/core/dev_mcast.c                  :      18        2        3
linux/net/core/dst.c                        :      68       22        5
linux/net/core/rtnetlink.c                  :      14        2        0
linux/net/core/skbuff.c                     :      20        1        6
linux/net/core/sock.c                       :      89       38       19
linux/net/decnet/Config.in                  :      13       13        0
linux/net/decnet/Makefile                   :      30       30        0
linux/net/decnet/README                     :      18        3       10
linux/net/decnet/TODO                       :      59       59        0
linux/net/decnet/af_decnet.c                :    2192     2192        0
linux/net/decnet/dn_dev.c                   :    1390     1390        0
linux/net/decnet/dn_fib.c                   :     805      805        0
linux/net/decnet/dn_neigh.c                 :     627      627        0
linux/net/decnet/dn_nsp_in.c                :     703      703        0
linux/net/decnet/dn_nsp_out.c               :     640      640        0
linux/net/decnet/dn_raw.c                   :     383      383        0
linux/net/decnet/dn_route.c                 :    1028     1028        0
linux/net/decnet/dn_timer.c                 :     164      164        0
linux/net/decnet/sysctl_net_decnet.c        :     473      473        0
linux/net/ethernet/eth.c                    :      21        4        1
linux/net/ipv4/af_inet.c                    :     112       25       28
linux/net/ipv4/devinet.c                    :      59       10        2
linux/net/ipv4/fib_hash.c                   :     279       48       18
linux/net/ipv4/fib_rules.c                  :     147       27        7
linux/net/ipv4/icmp.c                       :      21        7        2
linux/net/ipv4/igmp.c                       :      28        5        3
linux/net/ipv4/ip_fragment.c                :     107       18        9
linux/net/ipv4/ip_input.c                   :     330       85      167
linux/net/ipv4/ip_masq_mfw.c                :       8        1        1
linux/net/ipv4/ipconfig.c                   :      26        6        2
linux/net/ipv4/proc.c                       :      49        5       10
linux/net/ipv4/raw.c                        :     160       82       12
linux/net/ipv4/route.c                      :     345       60       32
linux/net/ipv4/tcp.c                        :     279       69       27
linux/net/ipv4/tcp_input.c                  :     124       46        9
linux/net/ipv4/tcp_ipv4.c                   :     583      140       78
linux/net/ipv4/tcp_output.c                 :      33        5        1
linux/net/ipv4/tcp_timer.c                  :     315       93       68
linux/net/ipv4/timer.c                      :      54       11        6
linux/net/ipv4/udp.c                        :     181       18       42
linux/net/ipv6/addrconf.c                   :      60        9        2
linux/net/ipv6/exthdrs.c                    :       8        1        1
linux/net/ipv6/icmp.c                       :      24        3        1
linux/net/ipv6/mcast.c                      :      25        4        1
linux/net/ipv6/proc.c                       :      56        6        9
linux/net/ipv6/raw.c                        :      67        9        7
linux/net/ipv6/tcp_ipv6.c                   :     363       83       45
linux/net/ipv6/udp.c                        :     101       13        9
linux/net/irda/af_irda.c                    :     460      269       30
linux/net/irda/crc.c                        :      19        4        4
linux/net/irda/discovery.c                  :      71       35       12
linux/net/irda/ircomm/ircomm_common.c       :     511      109      106
linux/net/irda/ircomm/irvtd_driver.c        :     112       15       13
linux/net/irda/irda_device.c                :     383      264       14
linux/net/irda/iriap.c                      :     225       42       38
linux/net/irda/iriap_event.c                :      24        4        4
linux/net/irda/irlan/irlan_client.c         :     191       36       40
linux/net/irda/irlan/irlan_client_event.c   :      48        6        6
linux/net/irda/irlan/irlan_common.c         :     363       86       65
linux/net/irda/irlan/irlan_eth.c            :     184       48       64
linux/net/irda/irlan/irlan_event.c          :      41        8        8
linux/net/irda/irlan/irlan_filter.c         :      70       14        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_comp.c                 :      27        4        4
linux/net/irda/irlap_event.c                :     212       52       44
linux/net/irda/irlap_frame.c                :      41        6        6
linux/net/irda/irlmp.c                      :     261       79       57
linux/net/irda/irlmp_frame.c                :     132       27       25
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                      :      78       23        7
linux/net/irda/irproc.c                     :     104       26       21
linux/net/irda/irsysctl.c                   :      19        4        4
linux/net/irda/irttp.c                      :     221       38       36
linux/net/irda/qos.c                        :      27        6        5
linux/net/irda/wrapper.c                    :     408      174      158
linux/net/netrom/nr_route.c                 :      33       11        5
linux/net/netsyms.c                         :      63       12        5
linux/net/rose/rose_route.c                 :      33       11        5
linux/net/sched/sch_api.c                   :      16        3        0
linux/net/sched/sch_generic.c               :      22        5        0
linux/net/socket.c                          :      21        7        1
linux/net/unix/af_unix.c                    :      42        7        5
linux/net/x25/af_x25.c                      :      24       10        4
-- 
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.
#!/bin/sh
# this is part 02 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+work with every existing HL driver. I was able to successfully open X.25
X connections on top of the isdnloop driver and the hisax driver.
X "x25iface"-encapsulation bypasses demand dialing. Dialing will be
-initiated when the upper (x25 packet) layer requests the lapb datalink to
-be established. But hangup timeout is still active. The connection
-will not automatically be re-established by the isdn_net module
-itself when new data arrives after the hangup timeout. But
-the x25 network code will re-establish the datalink connection
-(resulting in re-dialing and an x25 protocol reset) when new data is
-to be transmitted. (This currently does not work properly with the
-isdnloop driver, see "known problems" below)
+initiated when the upper (X.25 packet) layer requests the lapb datalink to
+be established. But hangup timeout is still active. Whenever a hangup
+occurs, all existing X.25 connections on that link will be cleared
+It is recommended to use sufficiently large hangup-timeouts for the
+isdn interfaces.
X 
X 
X In order to set up a conforming protocol stack you also need to
@@ -114,104 +107,64 @@
X    isdnctrl l2_prot <iface-name> x25dce
X 
X However, x25dte or x25dce is currently not supported by any real HL
-level driver. The main difference between x75 and x25dte/dce is that
+level driver. The main difference between x75i and x25dte/dce is that
X x25d[tc]e uses fixed lap_b addresses. With x75i, the side which
X initiates the isdn connection uses the DTE's lap_b address while the
-called side used the DCE's lap_b address. Thus, l2_prot x75i will
-probably work if you access a public x25 network as long as the
-corresponding isdn connection is set up by you. However, I've never
-tested this.
-
-
+called side used the DCE's lap_b address. Thus, l2_prot x75i might
+probably work if you access a public X.25 network as long as the
+corresponding isdn connection is set up by you. At least one test
+was successful to connect via isdn4linux to an X.25 switch using this
+trick. At the switch side, a terminal adapter X.21 was used to connect
+it to the isdn.
X 
-How to use the test installation?
X 
+How to set up a test installation?
+==================================
X 
-To test x25 on top of isdn, you need to get
+To test X.25 on top of isdn, you need to get
X 
-- a patched version of the "isdnctrl" program that supports setting the new
-  x25 specific parameters.
+- a recent version of the "isdnctrl" program that supports setting the new
+  X.25 specific parameters.
X 
-- the x25-utils-2.1.x package from ftp.pspt.fi/pub/ham/linux/ax25
-  or any mirror site (i.e. ftp://ftp.gwdg.de/pub/linux/misc/ax25/).
+- the x25-utils-2.X package from 
+  ftp://ftp.hes.iki.fi/pub/ham/linux/ax25/x25utils-*
+  (don't confuse the x25-utils with the ax25-utils)
X 
-- a kernel patch that enhances isdn4linux to provide x25 network
-  interface support. (This file is part of that kernel patch).
-
-- an application that uses linux AF_X25 sockets program. 
+- an application program that uses linux PF_X25 sockets (some are
+  contained in the x25-util package).
X 
X Before compiling the user level utilities make sure that the compiler/
-preprocessor will fetch the proper (patched) kernel header files. Either make
-/usr/include/linux a symbolic link pointing to your developer kernel's
-include/linux directory or set the appropriate compiler flags.
-
-It is recommended that all isdn drivers and the x25 PLP protocol 
-are compiled as loadable modules. Like this, you can recover
-from certain errors by simply unloading and reloading the modules.
+preprocessor will fetch the proper kernel header files of this kernel
+source tree. Either make /usr/include/linux a symbolic link pointing to 
+this kernel's include/linux directory or set the appropriate compiler flags.
X 
X When all drivers and interfaces are loaded and configured you need to
-ifconfig the network interfaces up and add x25-routes to them. Use
+ifconfig the network interfaces up and add X.25-routes to them. Use
X the usual ifconfig tool.
X 
X ifconfig <iface-name> up
X 
X But a special x25route tool (distributed with the x25-util package)
-is needed to set up x25 routes. I.e. 
+is needed to set up X.25 routes. I.e. 
X 
X x25route add 01 <iface-name>
X 
-will cause all x.25 connections to the destination x.25-address
+will cause all x.25 connections to the destination X.25-address
X "01" to be routed to your created isdn network interface.
X 
-
-There are currently no real x25 applications available. However, for
+There are currently no real X.25 applications available. However, for
X tests, the x25-utils package contains a modified version of telnet
-and telnetd that uses x25 sockets instead of tcp/ip sockets. Use
-this for your first tests. Furthermore, there is an x25.echod and a client
-named "eftp" (which contains some experimental code to download files
-from a remote eft server using the EUROfile transfer protocol).
-It available at ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/eftp4linux-*
+and telnetd that uses X.25 sockets instead of tcp/ip sockets. You can
+use those for your first tests. Furthermore, you might check
+ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/ which contains some
+alpha-test implementation ("eftp4linux") of the EUROfile transfer
+protocol.
+
+The scripts distributed with the eftp4linux test releases might also
+provide useful examples for setting up X.25 on top of isdn.
X 
X The x25-utility package also contains an x25trace tool that can be
-used to monitor x25 packets received by the network interfaces.
+used to monitor X.25 packets received by the network interfaces.
X The /proc/net/x25* files also contain useful information. 
X 
-The eftp4linux test release also contains an "ix25test" script that can
-be used for testing x25 on top of isdn4linux. Edit
-this script according to your local needs and then call it as
-
-ix25test start
-
-This will set up a sample configuration using the isdnloop and hisax
-driver and create some isdn network interfaces.
-It is recommended that all other isdn drivers and the
-x25 module are unloaded before calling this script.
-
-
-
-Known problems and deficiencies:
-
-The isdnloop HL driver apparently has problems to re-establish a
-connection that has been hung up from the outgoing device. You have to
-unload the isdnloop driver after the faked isdn-connection is closed
-and insmod it again. With the Hisax driver, this problem is not present.
-
-Sometimes the x25 module cannot be unloaded (decrementation of its use
-count seems to get lost occasionally).
-
-Using the x25 based telnet and telnetd programm to establish connection
-from your own to your own computer repeatedly sometimes totally locked
-up my system. However, this kernel patch also modifies
-net/x25/af_x25.c to include a workaround. With this workaround
-enabled, my system is stable. (If you want to disable the
-workaround, just undefine ISDN_X25_FIXES in af_x25.c).
-
-The latter problem could be reproduced by using hisax as well as the
-isdnloop driver. It seems that it is not caused by the isdn code.
-Somehow, the inode of a socket is freed while a process still refers
-the socket's wait queue. This causes problems when the process tries to
-remove itself from the wait queue (referred by the dangling
-sock->sleep pointer) before returning from a select() system call.
-
X - Henner
-
diff -u --recursive --new-file v2.3.3/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt
--- v2.3.3/linux/Documentation/networking/decnet.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/decnet.txt	Wed May 26 09:36:36 1999
@@ -0,0 +1,146 @@
+                    Linux DECnet Networking Layer Information
+                   ===========================================
+
+1) Other documentation....
+
+   o Project Home Pages
+       http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html - Kernel info
+       http://linux.dreamtime.org/decnet/                  - Userland tools
+
+   o FTP sites
+       ftp://ftp.sucs.swan.ac.uk/pub/Linux/DECnet/
+                - Swansea University Computer Society DECnet Archive
+                  (contains kernel patches and info)
+                - Mirror of userland tools on ftp.dreamtime.org
+
+        ftp://ftp.dreamtime.org/pub/linux/decnet/
+                - Patrick Caulfield's archive of userland tools and
+                  Eduardo Serrat's kernel patches
+
+2) Configuring the kernel
+
+Be sure to turn on the following options:
+
+    CONFIG_DECNET (obviously)
+    CONFIG_PROCFS (to see what's going on)
+    CONFIG_SYSCTL (for easy configuration)
+
+if you want to try out router support (not properly debugged and not
+complete yet), you'll need the following options as well...
+
+    CONFIG_DECNET_RAW (to receive routing packets)
+    CONFIG_DECNET_ROUTER (to be able to add/delete routes)
+    CONFIG_NETLINK (to allow rtnetlink)
+    CONFIG_RTNETLINK (for communication with the kernel routing layer)
+
+3) Command line options
+
+The kernel command line takes options looking like the following:
+
+    decnet=1,2,1
+
+the first two numbers are the node address 1,2 = 1.2 (yes, you must use
+commas when specifying them). The third number is the level number for routers
+and is optional. It is probably a good idea to set the DECnet address on boot
+like this rather than trying to do it later.
+
+There are also equivalent options for modules. The node address and type can
+also be set through the /proc/sys/net/decnet/ files, as can other system
+parameters.
+
+Currently the only supported device is ethernet. You'll have to set the
+ethernet address of your ethernet card according to the DECnet address
+of the node in order for it to be recognised (and thus appear in
+/proc/net/decnet_dev). There is a utility available at the above
+FTP sites called dn2ethaddr which can compute the correct ethernet
+address to use. The address can be set by ifconfig either before at
+at the time the device is brought up. If you are using RedHat you can
+add the line:
+
+    MACADDR=AA:00:04:00:03:04
+
+or something similar, to /etc/sysconfig/network-scripts/ifcfg-eth0 or
+wherever your network card's configuration lives.
+
+You will also need to set /proc/sys/net/decnet/default_device to the
+device you want DECnet to route packets out of when no specific route
+is available. Usually this will be eth0, for example:
+
+    echo -n "eth0" >/proc/sys/net/decnet/default_device
+
+There is a list of what the other files under /proc/sys/net/decnet/ do
+on the kernel patch web site (shown above).
+
+4) How can I tell if its working ?
+
+Here is a quick guide of what to look for in order to know if your DECnet
+kernel subsystem is working.
+
+   - Is the node address set (see /proc/sys/net/decnet/node_address)
+   - Is the node of the correct type (see /proc/sys/net/decnet/node_type)
+   - Is the Ethernet MAC address of each Ethernet card set to match
+     the DECnet address. If in doubt use the dn2ethaddr utility available
+     at the ftp archive.
+   - If the previous two steps are satisfied, and the Ethernet card is up,
+     you should find that it is listed in /proc/net/decnet_dev and also
+     that it appears as a directory in /proc/sys/net/decnet/conf/. The
+     loopback device (lo) should also appear and is required to communicate
+     within a node.
+   - If you have any DECnet routers on your network, they should appear
+     in /proc/net/decnet_neigh, otherwise this file will only contain the
+     entry for the node itself (if it doesn't check to see if lo is up).
+   - If you want to send to any node which is not listed in the
+     /proc/net/decnet_neigh file, you'll need to set the default device
+     to point to an Ethernet card with connection to a router. This is
+     again done with the /proc/sys/net/decnet/default_device file.
+   - Try starting a simple server and client, like the dnping/dnmirror
+     over the loopback interface. With luck they should communicate.
+     For this step and those after, you'll need the DECnet library
+     which can be obtained from the above ftp sites as well as the
+     actual utilities themselves.
+   - If this seems to work, then try talking to a node on your local
+     network, and see if you can obtain the same results.
+   - At this point you are on your own... :-)
+
+5) How to send a bug report
+
+If you've found a bug and want to report it, then there are several things
+you can do to help me work out exactly what it is that is wrong. Useful
+information (a lot of which is essential) includes:
+
+ - What kernel version are you running ?
+ - What version of the patch are you running ?
+ - How far though the above set of tests can you get ?
+ - What is in the /proc/decnet* files and /proc/sys/net/decnet/* files ?
+ - Which services are you running ?
+ - Which client caused the problem ?
+ - How much data was being transfered ?
+ - Was the network congested ?
+ - If there was a kernel panic, please run the output through ksymoops
+   before sending it to me, otherwise its _useless_.
+ - How can the problem be reproduced ?
+ - Can you use tcpdump to get a trace ? (N.B. Most (all?) versions of 
+   tcpdump don't understand how to dump DECnet properly, so including
+   the hex listing of the packet contents is essential, usually the -x flag.
+   You may also need to increase the length grabbed with the -s flag)
+
+6) Mailing list
+
+If you are keen to get involved in development, or want to ask questions
+about configuration, or even just report bugs, then there is a mailing
+list that you can join: send mail to majo...@dreamtime.org with
+
+subscribe linux-decnet
+
+as the body of the message.
+
+7) Legal Info
+
+The Linux DECnet project team have placed their code under the GPL. The
+software is provided "as is" and without warranty express or implied.
+DECnet is a trademark of Compaq. This software is not a product of
+Compaq. We acknowledge the help of people at Compaq in providing extra
+documentation above and beyond what was previously publicly available.
+
+Steve Whitehouse <Ste...@ACM.org>
+
diff -u --recursive --new-file v2.3.3/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330
--- v2.3.3/linux/Documentation/sound/CMI8330	Sun Mar  7 15:22:06 1999
+++ linux/Documentation/sound/CMI8330	Wed May 26 09:29:34 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.3.3/linux/Documentation/sound/CMI8338 linux/Documentation/sound/CMI8338
--- v2.3.3/linux/Documentation/sound/CMI8338	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/CMI8338	Wed May 26 09:36:36 1999
@@ -0,0 +1,32 @@
+Audio driver for CM8338/CM8738 chips by Chen-Li Tien
+
+   Be aware: C-Media Electronics Inc. is basically an IC design house,
+   and whose development of software drivers is mainly for use by its OEM
+   customers in their products. C-Media Electronics Inc. itself does not
+   manufacture end-user products, such as PC or sound cards, so it can
+   not fully control the drivers provided to consumers. Drivers provided
+   at this site, therefore, MAY NOT BE APPLICABLE to all sound cards.
+   Drivers you download from this site may function well at certain
+   situation, but C-Media Electronics Inc. does not give any guarantee or
+   assurances. Please be aware that these drivers might cause some
+   technical difficulties when installed
+
+
+1. Config cm8338 driver by 'make menuconfig' or 'make config' command.
+
+2. Please select Sound Card (CONFIG_SOUND=m) support and CMPCI driver (CONFIG_SOUND_CMPCI=m) as modules. Resident mode not tested.
+
+3. Compile the kernel if necessary.
+
+4. Compile the modules by 'make modules'.
+
+5. Install the modules by 'make modules_install'
+
+6. Before first time to run the driver, create module dependency by 'depmod -a'
+
+7. To install the driver, enter 'modprobe cmpci'.
+
+
+Bugs:
+
+1. Real player cannot be run (the same as es1371).
diff -u --recursive --new-file v2.3.3/linux/Makefile linux/Makefile
--- v2.3.3/linux/Makefile	Sat May 15 23:46:02 1999
+++ linux/Makefile	Mon May 17 09:55:04 1999
@@ -1,6 +1,6 @@
X VERSION = 2
X PATCHLEVEL = 3
-SUBLEVEL = 2
+SUBLEVEL = 4
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.3.3/linux/README linux/README
--- v2.3.3/linux/README	Fri May 14 18:55:11 1999
+++ linux/README	Sun May 30 10:17:43 1999
@@ -46,11 +46,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
@@ -62,7 +62,7 @@
X  - If you install the full sources, do a
X 
X 		cd /usr/src
-		gzip -cd linux-2.3.XX.tar.gz | tar xfv -
+		gzip -cd linux-2.3.XX.tar.gz | tar xvf -
X 
X    to get it all put in place. Replace "XX" with the version number of the
X    latest kernel.
@@ -233,7 +233,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.3.3/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.3.3/linux/arch/alpha/kernel/process.c	Sat May 15 23:46:03 1999
+++ linux/arch/alpha/kernel/process.c	Sat May 22 13:46:08 1999
@@ -58,10 +58,10 @@
X static struct file * init_fd_array[NR_OPEN] = { NULL, };
X static struct files_struct init_files = INIT_FILES;
X static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
+struct mm_struct init_mm = INIT_MM(init_mm);
X 
X union task_union init_task_union __attribute__((section("init_task")))
-	 = { task: INIT_TASK };
+	 = { task: INIT_TASK(init_task_union.task) };
X 
X /*
X  * No need to acquire the kernel lock, we're entirely local..
diff -u --recursive --new-file v2.3.3/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v2.3.3/linux/arch/alpha/kernel/ptrace.c	Tue Dec 29 16:17:00 1998
+++ linux/arch/alpha/kernel/ptrace.c	Sat May 22 12:42:04 1999
@@ -506,7 +506,8 @@
X 		     (current->uid != child->uid) ||
X 		     (current->gid != child->egid) ||
X 		     (current->gid != child->sgid) ||
-		     (current->gid != child->gid))
+		     (current->gid != child->gid) ||
+		     (!cap_issubset(child->cap_permitted, current->cap_permitted)))
X 		    && !capable(CAP_SYS_PTRACE))
X 			goto out;
X 		/* the same process cannot be attached many times */
diff -u --recursive --new-file v2.3.3/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c
--- v2.3.3/linux/arch/arm/kernel/ptrace.c	Wed Sep  9 08:56:58 1998
+++ linux/arch/arm/kernel/ptrace.c	Sat May 22 12:42:04 1999
@@ -580,6 +580,7 @@
X 		    (current->uid != child->uid) ||
X 	 	    (current->gid != child->egid) ||
X 	 	    (current->gid != child->sgid) ||
+		    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
X 	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
X 			goto out;
X 		/* the same process cannot be attached many times */
diff -u --recursive --new-file v2.3.3/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.3/linux/arch/i386/defconfig	Sat May 15 23:46:03 1999
+++ linux/arch/i386/defconfig	Mon May 31 09:01:50 1999
@@ -304,8 +304,10 @@
X # CONFIG_USB_OHCI_HCD is not set
X CONFIG_USB_MOUSE=y
X CONFIG_USB_KBD=y
+CONFIG_USB_HUB=y
X # CONFIG_USB_AUDIO is not set
X # CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
X 
X #
X # Filesystems
diff -u --recursive --new-file v2.3.3/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v2.3.3/linux/arch/mips/kernel/ptrace.c	Tue Oct 20 13:52:54 1998
+++ linux/arch/mips/kernel/ptrace.c	Sat May 22 12:42:04 1999
@@ -297,6 +297,7 @@
X 		    (current->uid != child->uid) ||
X 	 	    (current->gid != child->egid) ||
X 		    (current->gid != child->sgid) ||
+		    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
X 	 	    (current->gid != child->gid)) && 
X 		    !capable(CAP_SYS_PTRACE)) {
X 			res = -EPERM;
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.3.3/linux/arch/ppc/Makefile	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/Makefile	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.3.3/linux/arch/ppc/boot/Makefile	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/boot/Makefile	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.3.3/linux/arch/ppc/boot/misc.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/boot/misc.c	Sat May 22 13:03:00 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.65 1999/05/17 19:11:13 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.3.3/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.3.3/linux/arch/ppc/chrpboot/Makefile	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/chrpboot/Makefile	Sat May 22 13:03:00 1999
@@ -23,15 +23,21 @@
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
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.3.3/linux/arch/ppc/coffboot/Makefile	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/coffboot/Makefile	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.3.3/linux/arch/ppc/common_defconfig	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/common_defconfig	Sat May 22 13:03:00 1999
@@ -7,21 +7,24 @@
X #
X CONFIG_PPC=y
X CONFIG_6xx=y
+# CONFIG_PPC64 is not set
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
X # CONFIG_SMP is not set
+CONFIG_MACH_SPECIFIC=y
+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 +35,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
@@ -48,7 +51,6 @@
X # CONFIG_TOTALMP is not set
X CONFIG_BOOTX_TEXT=y
X # CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
X 
X #
X # Plug and Play support
@@ -66,7 +68,9 @@
X #
X # CONFIG_BLK_DEV_HD_IDE is not set
X CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
X CONFIG_BLK_DEV_IDECD=y
+# CONFIG_IDECD_SLOTS is not set
X # CONFIG_BLK_DEV_IDETAPE is not set
X CONFIG_BLK_DEV_IDEFLOPPY=y
X # CONFIG_BLK_DEV_IDESCSI is not set
@@ -75,13 +79,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
@@ -89,6 +95,7 @@
X # CONFIG_BLK_DEV_XD is not set
X CONFIG_PARIDE_PARPORT=y
X # CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_IDE_MODES=y
X # CONFIG_BLK_DEV_HD is not set
X 
X #
@@ -151,12 +158,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,14 +198,8 @@
X # CONFIG_SCSI_NCR53C406A is not set
X # CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_NCR53C8XX is not set
X # 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
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
X # CONFIG_SCSI_PCI2220I is not set
@@ -236,7 +237,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
@@ -296,32 +297,18 @@
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 +324,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 #
@@ -390,10 +367,11 @@
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
+# CONFIG_EFS_FS is not set
X CONFIG_ISO9660_FS=y
X # CONFIG_JOLIET is not set
X # CONFIG_MINIX_FS is not set
@@ -477,4 +455,4 @@
X #
X CONFIG_MAGIC_SYSRQ=y
X # CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.3/linux/arch/ppc/config.in	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/config.in	Sat May 22 13:03:00 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.92 1999/04/30 05:41:43 cort Exp $
+# $Id: config.in,v 1.93 1999/05/14 22:36:58 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.3.3/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.3/linux/arch/ppc/defconfig	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/defconfig	Sat May 22 13:03:00 1999
@@ -7,21 +7,24 @@
X #
X CONFIG_PPC=y
X CONFIG_6xx=y
+# CONFIG_PPC64 is not set
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
X # CONFIG_SMP is not set
+CONFIG_MACH_SPECIFIC=y
+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 +35,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
@@ -48,7 +51,6 @@
X # CONFIG_TOTALMP is not set
X CONFIG_BOOTX_TEXT=y
X # CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
X 
X #
X # Plug and Play support
@@ -66,7 +68,9 @@
X #
X # CONFIG_BLK_DEV_HD_IDE is not set
X CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
X CONFIG_BLK_DEV_IDECD=y
+# CONFIG_IDECD_SLOTS is not set
X # CONFIG_BLK_DEV_IDETAPE is not set
X CONFIG_BLK_DEV_IDEFLOPPY=y
X # CONFIG_BLK_DEV_IDESCSI is not set
@@ -75,13 +79,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
@@ -89,6 +95,7 @@
X # CONFIG_BLK_DEV_XD is not set
X CONFIG_PARIDE_PARPORT=y
X # CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_IDE_MODES=y
X # CONFIG_BLK_DEV_HD is not set
X 
X #
@@ -151,12 +158,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,14 +198,8 @@
X # CONFIG_SCSI_NCR53C406A is not set
X # CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_NCR53C8XX is not set
X # 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
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
X # CONFIG_SCSI_PCI2220I is not set
@@ -236,7 +237,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
@@ -296,32 +297,18 @@
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 +324,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 #
@@ -390,10 +367,11 @@
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
+# CONFIG_EFS_FS is not set
X CONFIG_ISO9660_FS=y
X # CONFIG_JOLIET is not set
X # CONFIG_MINIX_FS is not set
@@ -477,4 +455,4 @@
X #
X CONFIG_MAGIC_SYSRQ=y
X # CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.3.3/linux/arch/ppc/kernel/Makefile	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/Makefile	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.3.3/linux/arch/ppc/kernel/chrp_pci.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/chrp_pci.c	Sat May 22 13:03:00 1999
@@ -8,6 +8,7 @@
X #include <linux/string.h>
X #include <linux/init.h>
X #include <linux/openpic.h>
+#include <linux/ide.h>
X 
X #include <asm/io.h>
X #include <asm/pgtable.h>
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.3/linux/arch/ppc/kernel/chrp_setup.c	Fri May 14 18:55:12 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Sat May 22 13:03:00 1999
@@ -286,29 +286,6 @@
X 	if ( !strncmp("MOT", get_property(find_path_device("/"),
X 					  "model", NULL),3) )
X 		*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
-	 */
-	if ( !strncmp("F5", get_property(find_path_device("/"),
-					 "ibm,model-class", NULL),2) )
-	{
-#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		
-	}
X }
X 
X void
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.3/linux/arch/ppc/kernel/head.S	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/head.S	Sat May 22 13:03:00 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.131 1999/05/14 22:37:21 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 */
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.3.3/linux/arch/ppc/kernel/mbx_setup.c	Fri May 14 18:55:12 1999
+++ linux/arch/ppc/kernel/mbx_setup.c	Sat May 22 13:03:00 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: mbx_setup.c,v 1.9 1999/04/28 11:54:09 davem Exp $
+ * $Id: mbx_setup.c,v 1.10 1999/05/14 07:24:19 davem Exp $
X  *
X  *  linux/arch/ppc/kernel/setup.c
X  *
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.3.3/linux/arch/ppc/kernel/misc.S	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/misc.S	Sat May 22 13:03:00 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  */
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.3.3/linux/arch/ppc/kernel/pmac_setup.c	Fri May 14 18:55:12 1999
+++ linux/arch/ppc/kernel/pmac_setup.c	Sat May 22 13:03:00 1999
@@ -41,6 +41,7 @@
X #include <linux/blk.h>
X #include <linux/vt_kern.h>
X #include <linux/console.h>
+#include <linux/ide.h>
X #include <asm/prom.h>
X #include <asm/system.h>
X #include <asm/pgtable.h>
@@ -543,17 +544,18 @@
X         ppc_generic_ide_fix_driveid(id);
X }
X 
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
X /* This is declared in drivers/block/ide-pmac.c */
X void pmac_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
-
+#else
X /*
X  * This registers the standard ports for this architecture with the IDE
X  * driver.
X  */
-void
-ide_init_default_hwifs(void)
+void pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
X {
X }
+#endif
X #endif
X 
X __initfunc(void
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.3.3/linux/arch/ppc/kernel/prep_pci.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/prep_pci.c	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.3.3/linux/arch/ppc/kernel/prep_setup.c	Fri May 14 18:55:12 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Sat May 22 13:03:00 1999
@@ -33,6 +33,7 @@
X #include <linux/timex.h>
X #include <linux/pci.h>
X #include <linux/openpic.h>
+#include <linux/ide.h>
X 
X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -247,7 +248,7 @@
X 	case _PREP_Motorola:
X 		/* Enable L2.  Assume we don't need to flush -- Cort*/
X 		*(unsigned char *)(0x8000081c) |= 3;
-		ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
+		ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
X 		break;
X 	case _PREP_Radstone:
X 		ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
@@ -774,10 +775,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.3.3/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.3.3/linux/arch/ppc/kernel/process.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/process.c	Sat May 22 13:03:00 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: process.c,v 1.83 1999/05/10 04:43:43 cort Exp $
+ * $Id: process.c,v 1.85 1999/05/16 21:27:08 cort Exp $
X  *
X  *  linux/arch/ppc/kernel/process.c
X  *
@@ -51,8 +51,8 @@
X static struct file * init_fd_array[NR_OPEN] = { NULL, };
X static struct files_struct init_files = INIT_FILES;
X static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
-union task_union init_task_union = { INIT_TASK };
+struct mm_struct init_mm = INIT_MM(init_mm);
+union task_union init_task_union = { INIT_TASK(init_task_union.task) };
X /* only used to get secondary processor up */
X struct task_struct *current_set[NR_CPUS] = {&init_task, };
X 
@@ -233,24 +233,6 @@
X 		}
X 	}
X out:
-}
-
-void instruction_dump (unsigned long *pc)
-{
-	int i;
-
-	if((((unsigned long) pc) & 3))
-                return;
-
-	printk("Instruction DUMP:");
-	for(i = -3; i < 6; i++)
-	{
-		unsigned long p;
-		if (__get_user( p, &pc[i] ))
-			break;
-		printk("%c%08lx%c",i?' ':'<',p,i?' ':'>');
-	}
-	printk("\n");
X }
X 
X void exit_thread(void)
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.3.3/linux/arch/ppc/kernel/ptrace.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/ptrace.c	Sat May 22 12:42:04 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.3.3/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- v2.3.3/linux/arch/ppc/kernel/residual.c	Fri May 14 18:55:12 1999
+++ linux/arch/ppc/kernel/residual.c	Sat May 22 13:03:00 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.15 1999/05/14 07:24:27 davem Exp $
X  *
X  * Code to deal with the PReP residual data.
X  *
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.3/linux/arch/ppc/kernel/setup.c	Fri May 14 18:55:12 1999
+++ linux/arch/ppc/kernel/setup.c	Sat May 22 13:03:00 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.133 1999/05/14 07:24:30 davem Exp $
X  * Common prep/pmac/chrp boot and setup code.
X  */
X 
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.3.3/linux/arch/ppc/kernel/softemu8xx.c	Wed Mar 10 21:30:32 1999
+++ linux/arch/ppc/kernel/softemu8xx.c	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.3.3/linux/arch/ppc/kernel/syscalls.c	Sat May  8 11:14:01 1999
+++ linux/arch/ppc/kernel/syscalls.c	Sat May 22 13:03:00 1999
@@ -205,15 +205,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.3.3/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.3.3/linux/arch/ppc/kernel/traps.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/traps.c	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.3.3/linux/arch/ppc/mm/fault.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/mm/fault.c	Sat May 22 13:03:00 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.3.3/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.3/linux/arch/ppc/mm/init.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/mm/init.c	Sat May 22 13:03:00 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.165 1999/05/14 22:37:29 cort Exp $
X  *
X  *  PowerPC version 
X  *    Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)
@@ -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.3.3/linux/arch/ppc/xmon/Makefile linux/arch/ppc/xmon/Makefile
--- v2.3.3/linux/arch/ppc/xmon/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/Makefile	Sat May 22 13:03:00 1999
@@ -0,0 +1,6 @@
+# Makefile for xmon
+
+O_TARGET = x.o
+O_OBJS = start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 02'
echo 'File patch-2.3.4 is continued in part 03'
echo 03 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 04 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+{ "bdnza-",  BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdnza+",  BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdnza",   BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC,	{ BDA } },
+{ "bdna",    BBO(16,BODNZ,1,0), BBOYBI_MASK, POWER,	{ BDA } },
+{ "bdnzla-", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdnzla+", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdnzla",  BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC,	{ BDA } },
+{ "bdnla",   BBO(16,BODNZ,1,1), BBOYBI_MASK, POWER,	{ BDA } },
+{ "bdz-",    BBO(16,BODZ,0,0), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdz+",    BBO(16,BODZ,0,0), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdz",     BBO(16,BODZ,0,0), BBOYBI_MASK, PPC|POWER,	{ BD } },
+{ "bdzl-",   BBO(16,BODZ,0,1), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdzl+",   BBO(16,BODZ,0,1), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdzl",    BBO(16,BODZ,0,1), BBOYBI_MASK, PPC|POWER,	{ BD } },
+{ "bdza-",   BBO(16,BODZ,1,0), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdza+",   BBO(16,BODZ,1,0), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdza",    BBO(16,BODZ,1,0), BBOYBI_MASK, PPC|POWER,	{ BDA } },
+{ "bdzla-",  BBO(16,BODZ,1,1), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdzla+",  BBO(16,BODZ,1,1), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdzla",   BBO(16,BODZ,1,1), BBOYBI_MASK, PPC|POWER,	{ BDA } },
+{ "blt-",    BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "blt+",    BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "blt",     BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bltl-",   BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bltl+",   BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bltl",    BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blta-",   BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "blta+",   BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "blta",    BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bltla-",  BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bltla+",  BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bltla",   BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgt-",    BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bgt+",    BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bgt",     BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgtl-",   BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bgtl+",   BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bgtl",    BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgta-",   BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgta+",   BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgta",    BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgtla-",  BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgtla+",  BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgtla",   BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "beq-",    BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "beq+",    BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "beq",     BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "beql-",   BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "beql+",   BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "beql",    BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "beqa-",   BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "beqa+",   BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "beqa",    BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "beqla-",  BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "beqla+",  BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "beqla",   BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bso-",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bso+",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bso",     BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bsol-",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bsol+",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bsol",    BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bsoa-",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bsoa+",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bsoa",    BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bsola-",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bsola+",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bsola",   BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bun-",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bun+",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bun",     BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "bunl-",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bunl+",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bunl",    BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "buna-",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "buna+",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "buna",    BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bunla-",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bunla+",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bunla",   BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bge-",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bge+",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bge",     BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgel-",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bgel+",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bgel",    BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgea-",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgea+",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgea",    BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgela-",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgela+",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgela",   BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnl-",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnl+",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnl",     BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnll-",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnll+",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnll",    BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnla-",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnla+",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnla",    BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnlla-",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnlla+",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnlla",   BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "ble-",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "ble+",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "ble",     BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blel-",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "blel+",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "blel",    BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blea-",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "blea+",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "blea",    BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "blela-",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "blela+",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "blela",   BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bng-",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bng+",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bng",     BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bngl-",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bngl+",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bngl",    BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnga-",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnga+",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnga",    BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bngla-",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bngla+",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bngla",   BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bne-",    BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bne+",    BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bne",     BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnel-",   BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnel+",   BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnel",    BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnea-",   BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnea+",   BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnea",    BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnela-",  BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnela+",  BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnela",   BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bns-",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bns+",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bns",     BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnsl-",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnsl+",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnsl",    BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnsa-",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnsa+",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnsa",    BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnsla-",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnsla+",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnsla",   BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnu-",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnu+",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnu",     BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "bnul-",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnul+",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnul",    BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "bnua-",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnua+",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnua",    BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bnula-",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnula+",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnula",   BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bdnzt-",  BBO(16,BODNZT,0,0), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnzt+",  BBO(16,BODNZT,0,0), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnzt",   BBO(16,BODNZT,0,0), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnztl",  BBO(16,BODNZT,0,1), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnzta",  BBO(16,BODNZT,1,0), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bdnzf-",  BBO(16,BODNZF,0,0), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnzf+",  BBO(16,BODNZF,0,0), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnzf",   BBO(16,BODNZF,0,0), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnzfl",  BBO(16,BODNZF,0,1), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnzfa",  BBO(16,BODNZF,1,0), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bt-",     BBO(16,BOT,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bt+",     BBO(16,BOT,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bt",	     BBO(16,BOT,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbt",     BBO(16,BOT,0,0), BBOY_MASK, POWER,		{ BI, BD } },
+{ "btl-",    BBO(16,BOT,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "btl+",    BBO(16,BOT,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "btl",     BBO(16,BOT,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbtl",    BBO(16,BOT,0,1), BBOY_MASK, POWER,		{ BI, BD } },
+{ "bta-",    BBO(16,BOT,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bta+",    BBO(16,BOT,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bta",     BBO(16,BOT,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbta",    BBO(16,BOT,1,0), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "btla-",   BBO(16,BOT,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "btla+",   BBO(16,BOT,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "btla",    BBO(16,BOT,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbtla",   BBO(16,BOT,1,1), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "bf-",     BBO(16,BOF,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bf+",     BBO(16,BOF,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bf",	     BBO(16,BOF,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbf",     BBO(16,BOF,0,0), BBOY_MASK, POWER,		{ BI, BD } },
+{ "bfl-",    BBO(16,BOF,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bfl+",    BBO(16,BOF,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bfl",     BBO(16,BOF,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbfl",    BBO(16,BOF,0,1), BBOY_MASK, POWER,		{ BI, BD } },
+{ "bfa-",    BBO(16,BOF,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bfa+",    BBO(16,BOF,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bfa",     BBO(16,BOF,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbfa",    BBO(16,BOF,1,0), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "bfla-",   BBO(16,BOF,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bfla+",   BBO(16,BOF,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bfla",    BBO(16,BOF,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbfla",   BBO(16,BOF,1,1), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "bdzt-",   BBO(16,BODZT,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdzt+",   BBO(16,BODZT,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdzt",    BBO(16,BODZT,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdztl-",  BBO(16,BODZT,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdztl+",  BBO(16,BODZT,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdztl",   BBO(16,BODZT,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdzta-",  BBO(16,BODZT,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdzta+",  BBO(16,BODZT,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdzta",   BBO(16,BODZT,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdztla",  BBO(16,BODZT,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bdzf-",   BBO(16,BODZF,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdzf+",   BBO(16,BODZF,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdzf",    BBO(16,BODZF,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdzfl-",  BBO(16,BODZF,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdzfl+",  BBO(16,BODZF,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdzfl",   BBO(16,BODZF,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdzfa-",  BBO(16,BODZF,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdzfa+",  BBO(16,BODZF,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdzfa",   BBO(16,BODZF,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdzfla",  BBO(16,BODZF,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bc-",     B(16,0,0),	B_MASK,		PPC,		{ BOE, BI, BDM } },
+{ "bc+",     B(16,0,0),	B_MASK,		PPC,		{ BOE, BI, BDP } },
+{ "bc",	     B(16,0,0),	B_MASK,		PPC|POWER,	{ BO, BI, BD } },
+{ "bcl-",    B(16,0,1),	B_MASK,		PPC,		{ BOE, BI, BDM } },
+{ "bcl+",    B(16,0,1),	B_MASK,		PPC,		{ BOE, BI, BDP } },
+{ "bcl",     B(16,0,1),	B_MASK,		PPC|POWER,	{ BO, BI, BD } },
+{ "bca-",    B(16,1,0),	B_MASK,		PPC,		{ BOE, BI, BDMA } },
+{ "bca+",    B(16,1,0),	B_MASK,		PPC,		{ BOE, BI, BDPA } },
+{ "bca",     B(16,1,0),	B_MASK,		PPC|POWER,	{ BO, BI, BDA } },
+{ "bcla-",   B(16,1,1),	B_MASK,		PPC,		{ BOE, BI, BDMA } },
+{ "bcla+",   B(16,1,1),	B_MASK,		PPC,		{ BOE, BI, BDPA } },
+{ "bcla",    B(16,1,1),	B_MASK,		PPC|POWER,	{ BO, BI, BDA } },
+
+{ "sc",      SC(17,1,0), 0xffffffff,	PPC,		{ 0 } },
+{ "svc",     SC(17,0,0), SC_MASK,	POWER,		{ LEV, FL1, FL2 } },
+{ "svcl",    SC(17,0,1), SC_MASK,	POWER,		{ LEV, FL1, FL2 } },
+{ "svca",    SC(17,1,0), SC_MASK,	POWER,		{ SV } },
+{ "svcla",   SC(17,1,1), SC_MASK,	POWER,		{ SV } },
+
+{ "b",	     B(18,0,0),	B_MASK,		PPC|POWER,	{ LI } },
+{ "bl",      B(18,0,1),	B_MASK,		PPC|POWER,	{ LI } },
+{ "ba",      B(18,1,0),	B_MASK,		PPC|POWER,	{ LIA } },
+{ "bla",     B(18,1,1),	B_MASK,		PPC|POWER,	{ LIA } },
+
+{ "mcrf",    XL(19,0),	XLBB_MASK|(3<<21)|(3<<16), PPC|POWER, { BF, BFA } },
+
+{ "blr",     XLO(19,BOU,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "br",      XLO(19,BOU,16,0), XLBOBIBB_MASK, POWER,	{ 0 } },
+{ "blrl",    XLO(19,BOU,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "brl",     XLO(19,BOU,16,1), XLBOBIBB_MASK, POWER,	{ 0 } },
+{ "bdnzlr",  XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlr",   XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlr-",  XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlr+",  XLO(19,BODZP,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlrl",  XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bltlr",   XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlr-",  XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlr+",  XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltr",    XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bltlrl",  XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltrl",   XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgtlr",   XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlr-",  XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlr+",  XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtr",    XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgtlrl",  XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtrl",   XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "beqlr",   XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlr-",  XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlr+",  XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqr",    XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "beqlrl",  XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqrl",   XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bsolr",   XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolr-",  XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolr+",  XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsor",    XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bsolrl",  XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsorl",   XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bunlr",   XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlr-",  XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlr+",  XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl",  XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr",   XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr-",  XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr+",  XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bger",    XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgelrl",  XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgerl",   XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnllr",   XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllr-",  XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllr+",  XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlr",    XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnllrl",  XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlrl",   XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "blelr",   XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelr-",  XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelr+",  XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bler",    XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "blelrl",  XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blerl",   XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnglr",   XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglr-",  XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglr+",  XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngr",    XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnglrl",  XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngrl",   XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnelr",   XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelr-",  XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelr+",  XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bner",    XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnelrl",  XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnerl",   XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnslr",   XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslr-",  XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslr+",  XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsr",    XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnslrl",  XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsrl",   XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnulr",   XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulr-",  XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulr+",  XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl",  XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "btlr",    XLO(19,BOT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlr-",   XLO(19,BOT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlr+",   XLO(19,BOTP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbtr",    XLO(19,BOT,16,0), XLBOBB_MASK, POWER,	{ BI } },
+{ "btlrl",   XLO(19,BOT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlrl-",  XLO(19,BOT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlrl+",  XLO(19,BOTP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbtrl",   XLO(19,BOT,16,1), XLBOBB_MASK, POWER,	{ BI } },
+{ "bflr",    XLO(19,BOF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflr-",   XLO(19,BOF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflr+",   XLO(19,BOFP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbfr",    XLO(19,BOF,16,0), XLBOBB_MASK, POWER,	{ BI } },
+{ "bflrl",   XLO(19,BOF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflrl-",  XLO(19,BOF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflrl+",  XLO(19,BOFP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbfrl",   XLO(19,BOF,16,1), XLBOBB_MASK, POWER,	{ BI } },
+{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlr",  XLO(19,BODZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflr",  XLO(19,BODZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bclr",    XLLK(19,16,0), XLYBB_MASK,	PPC,		{ BO, BI } },
+{ "bclrl",   XLLK(19,16,1), XLYBB_MASK,	PPC,		{ BO, BI } },
+{ "bclr+",   XLYLK(19,16,1,0), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bclrl+",  XLYLK(19,16,1,1), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bclr-",   XLYLK(19,16,0,0), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bclrl-",  XLYLK(19,16,0,1), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bcr",     XLLK(19,16,0), XLBB_MASK,	POWER,		{ BO, BI } },
+{ "bcrl",    XLLK(19,16,1), XLBB_MASK,	POWER,		{ BO, BI } },
+
+{ "crnot",   XL(19,33), XL_MASK,	PPC,		{ BT, BA, BBA } },
+{ "crnor",   XL(19,33),	XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "rfi",     XL(19,50),	0xffffffff,	PPC|POWER,	{ 0 } },
+{ "rfci",    XL(19,51),	0xffffffff,	PPC,		{ 0 } },
+
+{ "rfsvc",   XL(19,82),	0xffffffff,	POWER,		{ 0 } },
+
+{ "crandc",  XL(19,129), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "isync",   XL(19,150), 0xffffffff,	PPC,		{ 0 } },
+{ "ics",     XL(19,150), 0xffffffff,	POWER,		{ 0 } },
+
+{ "crclr",   XL(19,193), XL_MASK,	PPC,		{ BT, BAT, BBA } },
+{ "crxor",   XL(19,193), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crnand",  XL(19,225), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crand",   XL(19,257), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crset",   XL(19,289), XL_MASK,	PPC,		{ BT, BAT, BBA } },
+{ "creqv",   XL(19,289), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crorc",   XL(19,417), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crmove",  XL(19,449), XL_MASK,	PPC,		{ BT, BA, BBA } },
+{ "cror",    XL(19,449), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "bctr",    XLO(19,BOU,528,0), XLBOBIBB_MASK, PPC|POWER, { 0 } },
+{ "bctrl",   XLO(19,BOU,528,1), XLBOBIBB_MASK, PPC|POWER, { 0 } },
+{ "bltctr",  XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr",  XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr",  XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr",  XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr",  XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr",  XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr",  XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr",  XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr",  XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr",  XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr",  XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr",  XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "btctr",   XLO(19,BOT,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctr-",  XLO(19,BOT,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctr+",  XLO(19,BOTP,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctrl",  XLO(19,BOT,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctr",   XLO(19,BOF,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctr-",  XLO(19,BOF,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctr+",  XLO(19,BOFP,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctrl",  XLO(19,BOF,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bcctr",   XLLK(19,528,0), XLYBB_MASK, PPC,		{ BO, BI } },
+{ "bcctr-",  XLYLK(19,528,0,0), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcctr+",  XLYLK(19,528,1,0), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcctrl",  XLLK(19,528,1), XLYBB_MASK, PPC,		{ BO, BI } },
+{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcc",     XLLK(19,528,0), XLBB_MASK,	POWER,		{ BO, BI } },
+{ "bccl",    XLLK(19,528,1), XLBB_MASK,	POWER,		{ BO, BI } },
+
+{ "rlwimi",  M(20,0),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlimi",   M(20,0),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+
+{ "rlwimi.", M(20,1),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlimi.",  M(20,1),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+
+{ "rotlwi",  MME(21,31,0), MMBME_MASK,	PPC,		{ RA, RS, SH } },
+{ "clrlwi",  MME(21,31,0), MSHME_MASK,	PPC,		{ RA, RS, MB } },
+{ "rlwinm",  M(21,0),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlinm",   M(21,0),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+{ "rotlwi.", MME(21,31,1), MMBME_MASK,	PPC,		{ RA,RS,SH } },
+{ "clrlwi.", MME(21,31,1), MSHME_MASK,	PPC,		{ RA, RS, MB } },
+{ "rlwinm.", M(21,1),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlinm.",  M(21,1),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+
+{ "rlmi",    M(22,0),	M_MASK,		POWER|M601,	{ RA,RS,RB,MBE,ME } },
+{ "rlmi.",   M(22,1),	M_MASK,		POWER|M601,	{ RA,RS,RB,MBE,ME } },
+
+{ "rotlw",   MME(23,31,0), MMBME_MASK,	PPC,		{ RA, RS, RB } },
+{ "rlwnm",   M(23,0),	M_MASK,		PPC,		{ RA,RS,RB,MBE,ME } },
+{ "rlnm",    M(23,0),	M_MASK,		POWER,		{ RA,RS,RB,MBE,ME } },
+{ "rotlw.",  MME(23,31,1), MMBME_MASK,	PPC,		{ RA, RS, RB } },
+{ "rlwnm.",  M(23,1),	M_MASK,		PPC,		{ RA,RS,RB,MBE,ME } },
+{ "rlnm.",   M(23,1),	M_MASK,		POWER,		{ RA,RS,RB,MBE,ME } },
+
+{ "nop",     OP(24),	0xffffffff,	PPC,		{ 0 } },
+{ "ori",     OP(24),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "oril",    OP(24),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "oris",    OP(25),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "oriu",    OP(25),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "xori",    OP(26),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "xoril",   OP(26),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "xoris",   OP(27),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "xoriu",   OP(27),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "andi.",   OP(28),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "andil.",  OP(28),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "andis.",  OP(29),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "andiu.",  OP(29),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "rotldi",  MD(30,0,0), MDMB_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+{ "clrldi",  MD(30,0,0), MDSH_MASK,	PPC|B64,	{ RA, RS, MB6 } },
+{ "rldicl",  MD(30,0,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+{ "rotldi.", MD(30,0,1), MDMB_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+{ "clrldi.", MD(30,0,1), MDSH_MASK,	PPC|B64,	{ RA, RS, MB6 } },
+{ "rldicl.", MD(30,0,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+
+{ "rldicr",  MD(30,1,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, ME6 } },
+{ "rldicr.", MD(30,1,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, ME6 } },
+
+{ "rldic",   MD(30,2,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+{ "rldic.",  MD(30,2,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+
+{ "rldimi",  MD(30,3,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+{ "rldimi.", MD(30,3,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+
+{ "rotld",   MDS(30,8,0), MDSMB_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "rldcl",   MDS(30,8,0), MDS_MASK,	PPC|B64,	{ RA, RS, RB, MB6 } },
+{ "rotld.",  MDS(30,8,1), MDSMB_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "rldcl.",  MDS(30,8,1), MDS_MASK,	PPC|B64,	{ RA, RS, RB, MB6 } },
+
+{ "rldcr",   MDS(30,9,0), MDS_MASK,	PPC|B64,	{ RA, RS, RB, ME6 } },
+{ "rldcr.",  MDS(30,9,1), MDS_MASK,	PPC|B64,	{ RA, RS, RB, ME6 } },
+
+{ "cmpw",    XCMPL(31,0,0), XCMPL_MASK, PPC,		{ OBF, RA, RB } },
+{ "cmpd",    XCMPL(31,0,1), XCMPL_MASK, PPC|B64,	{ OBF, RA, RB } },
+{ "cmp",     X(31,0),	XCMP_MASK,	PPC,		{ BF, L, RA, RB } },
+{ "cmp",     X(31,0),	XCMPL_MASK,	POWER,		{ BF, RA, RB } },
+
+{ "twlgt",   XTO(31,4,TOLGT), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlgt",    XTO(31,4,TOLGT), XTO_MASK, POWER,		{ RA, RB } },
+{ "twllt",   XTO(31,4,TOLLT), XTO_MASK, PPC,		{ RA, RB } },
+{ "tllt",    XTO(31,4,TOLLT), XTO_MASK, POWER,		{ RA, RB } },
+{ "tweq",    XTO(31,4,TOEQ), XTO_MASK,	PPC,		{ RA, RB } },
+{ "teq",     XTO(31,4,TOEQ), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twlge",   XTO(31,4,TOLGE), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlge",    XTO(31,4,TOLGE), XTO_MASK, POWER,		{ RA, RB } },
+{ "twlnl",   XTO(31,4,TOLNL), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlnl",    XTO(31,4,TOLNL), XTO_MASK, POWER,		{ RA, RB } },
+{ "twlle",   XTO(31,4,TOLLE), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlle",    XTO(31,4,TOLLE), XTO_MASK, POWER,		{ RA, RB } },
+{ "twlng",   XTO(31,4,TOLNG), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlng",    XTO(31,4,TOLNG), XTO_MASK, POWER,		{ RA, RB } },
+{ "twgt",    XTO(31,4,TOGT), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tgt",     XTO(31,4,TOGT), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twge",    XTO(31,4,TOGE), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tge",     XTO(31,4,TOGE), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twnl",    XTO(31,4,TONL), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tnl",     XTO(31,4,TONL), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twlt",    XTO(31,4,TOLT), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tlt",     XTO(31,4,TOLT), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twle",    XTO(31,4,TOLE), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tle",     XTO(31,4,TOLE), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twng",    XTO(31,4,TONG), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tng",     XTO(31,4,TONG), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twne",    XTO(31,4,TONE), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tne",     XTO(31,4,TONE), XTO_MASK,	POWER,		{ RA, RB } },
+{ "trap",    XTO(31,4,TOU), 0xffffffff,	PPC,		{ 0 } },
+{ "tw",      X(31,4),	X_MASK,		PPC,		{ TO, RA, RB } },
+{ "t",       X(31,4),	X_MASK,		POWER,		{ TO, RA, RB } },
+
+{ "subfc",   XO(31,8,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sf",      XO(31,8,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subc",    XO(31,8,0,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfc.",  XO(31,8,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sf.",     XO(31,8,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subc.",   XO(31,8,0,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfco",  XO(31,8,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfo",     XO(31,8,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subco",   XO(31,8,1,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfco.", XO(31,8,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfo.",    XO(31,8,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subco.",  XO(31,8,1,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+
+{ "mulhdu",  XO(31,9,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulhdu.", XO(31,9,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "addc",    XO(31,10,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "a",       XO(31,10,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addc.",   XO(31,10,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "a.",      XO(31,10,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addco",   XO(31,10,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ao",      XO(31,10,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addco.",  XO(31,10,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ao.",     XO(31,10,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "mulhwu",  XO(31,11,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulhwu.", XO(31,11,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "mfcr",    X(31,19),	XRARB_MASK,	POWER|PPC,	{ RT } },
+
+{ "lwarx",   X(31,20),	X_MASK,		PPC,		{ RT, RA, RB } },
+
+{ "ldx",     X(31,21),	X_MASK,		PPC|B64,	{ RT, RA, RB } },
+
+{ "lwzx",    X(31,23),	X_MASK,		PPC,		{ RT, RA, RB } },
+{ "lx",      X(31,23),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "slw",     XRC(31,24,0), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sl",      XRC(31,24,0), X_MASK,	POWER,		{ RA, RS, RB } },
+{ "slw.",    XRC(31,24,1), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sl.",     XRC(31,24,1), X_MASK,	POWER,		{ RA, RS, RB } },
+
+{ "cntlzw",  XRC(31,26,0), XRB_MASK,	PPC,		{ RA, RS } },
+{ "cntlz",   XRC(31,26,0), XRB_MASK,	POWER,		{ RA, RS } },
+{ "cntlzw.", XRC(31,26,1), XRB_MASK,	PPC,		{ RA, RS } },
+{ "cntlz.",  XRC(31,26,1), XRB_MASK, 	POWER,		{ RA, RS } },
+
+{ "sld",     XRC(31,27,0), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "sld.",    XRC(31,27,1), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+
+{ "and",     XRC(31,28,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "and.",    XRC(31,28,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "maskg",   XRC(31,29,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "maskg.",  XRC(31,29,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "cmplw",   XCMPL(31,32,0), XCMPL_MASK, PPC,		{ OBF, RA, RB } },
+{ "cmpld",   XCMPL(31,32,1), XCMPL_MASK, PPC|B64,	{ OBF, RA, RB } },
+{ "cmpl",    X(31,32),	XCMP_MASK,	PPC,		{ BF, L, RA, RB } },
+{ "cmpl",    X(31,32),	XCMPL_MASK,	POWER,		{ BF, RA, RB } },
+
+{ "subf",    XO(31,40,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sub",     XO(31,40,0,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subf.",   XO(31,40,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sub.",    XO(31,40,0,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfo",   XO(31,40,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "subo",    XO(31,40,1,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfo.",  XO(31,40,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "subo.",   XO(31,40,1,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+
+{ "ldux",    X(31,53),	X_MASK,		PPC|B64,	{ RT, RAL, RB } },
+
+{ "dcbst",   X(31,54),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lwzux",   X(31,55),	X_MASK,		PPC,		{ RT, RAL, RB } },
+{ "lux",     X(31,55),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "cntlzd",  XRC(31,58,0), XRB_MASK,	PPC|B64,	{ RA, RS } },
+{ "cntlzd.", XRC(31,58,1), XRB_MASK,	PPC|B64,	{ RA, RS } },
+
+{ "andc",    XRC(31,60,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "andc.",   XRC(31,60,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "tdlgt",   XTO(31,68,TOLGT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdllt",   XTO(31,68,TOLLT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdeq",    XTO(31,68,TOEQ), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlge",   XTO(31,68,TOLGE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlnl",   XTO(31,68,TOLNL), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlle",   XTO(31,68,TOLLE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlng",   XTO(31,68,TOLNG), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdgt",    XTO(31,68,TOGT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdge",    XTO(31,68,TOGE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdnl",    XTO(31,68,TONL), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlt",    XTO(31,68,TOLT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdle",    XTO(31,68,TOLE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdng",    XTO(31,68,TONG), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdne",    XTO(31,68,TONE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "td",	     X(31,68),	X_MASK,		PPC|B64,	{ TO, RA, RB } },
+
+{ "mulhd",   XO(31,73,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulhd.",  XO(31,73,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "mulhw",   XO(31,75,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulhw.",  XO(31,75,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "mfmsr",   X(31,83),	XRARB_MASK,	PPC|POWER,	{ RT } },
+
+{ "ldarx",   X(31,84),	X_MASK,		PPC|B64,	{ RT, RA, RB } },
+
+{ "dcbf",    X(31,86),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lbzx",    X(31,87),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "neg",     XO(31,104,0,0), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+{ "neg.",    XO(31,104,0,1), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+{ "nego",    XO(31,104,1,0), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+{ "nego.",   XO(31,104,1,1), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+
+{ "mul",     XO(31,107,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "mul.",    XO(31,107,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "mulo",    XO(31,107,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "mulo.",   XO(31,107,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "clf",     X(31,118), XRB_MASK,	POWER,		{ RT, RA } },
+
+{ "lbzux",   X(31,119),	X_MASK,		PPC|POWER,	{ RT, RAL, RB } },
+
+{ "not",     XRC(31,124,0), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "nor",     XRC(31,124,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "not.",    XRC(31,124,1), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "nor.",    XRC(31,124,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "subfe",   XO(31,136,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfe",     XO(31,136,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subfe.",  XO(31,136,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfe.",    XO(31,136,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subfeo",  XO(31,136,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfeo",    XO(31,136,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subfeo.", XO(31,136,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfeo.",   XO(31,136,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "adde",    XO(31,138,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ae",      XO(31,138,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "adde.",   XO(31,138,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ae.",     XO(31,138,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addeo",   XO(31,138,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "aeo",     XO(31,138,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addeo.",  XO(31,138,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "aeo.",    XO(31,138,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "mtcr",    XFXM(31,144,0xff), XFXFXM_MASK|FXM_MASK, PPC|POWER, { RS }},
+{ "mtcrf",   X(31,144),	XFXFXM_MASK,	PPC|POWER,	{ FXM, RS } },
+
+{ "mtmsr",   X(31,146),	XRARB_MASK,	PPC|POWER,	{ RS } },
+
+{ "stdx",    X(31,149), X_MASK,		PPC|B64,	{ RS, RA, RB } },
+
+{ "stwcx.",  XRC(31,150,1), X_MASK,	PPC,		{ RS, RA, RB } },
+
+{ "stwx",    X(31,151), X_MASK,		PPC,		{ RS, RA, RB } },
+{ "stx",     X(31,151), X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "slq",     XRC(31,152,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "slq.",    XRC(31,152,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sle",     XRC(31,153,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sle.",    XRC(31,153,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "stdux",   X(31,181),	X_MASK,		PPC|B64,	{ RS, RAS, RB } },
+
+{ "stwux",   X(31,183),	X_MASK,		PPC,		{ RS, RAS, RB } },
+{ "stux",    X(31,183),	X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "sliq",    XRC(31,184,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "sliq.",   XRC(31,184,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "subfze",  XO(31,200,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfze",    XO(31,200,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfze.", XO(31,200,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfze.",   XO(31,200,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfzeo",   XO(31,200,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfzeo.",  XO(31,200,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "addze",   XO(31,202,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "aze",     XO(31,202,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addze.",  XO(31,202,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "aze.",    XO(31,202,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "addzeo",  XO(31,202,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "azeo",    XO(31,202,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "azeo.",   XO(31,202,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "mtsr",    X(31,210),	XRB_MASK|(1<<20), PPC|POWER|B32, { SR, RS } },
+
+{ "stdcx.",  XRC(31,214,1), X_MASK,	PPC|B64,	{ RS, RA, RB } },
+
+{ "stbx",    X(31,215),	X_MASK,		PPC|POWER,	{ RS, RA, RB } },
+
+{ "sllq",    XRC(31,216,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sllq.",   XRC(31,216,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sleq",    XRC(31,217,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sleq.",   XRC(31,217,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "subfme",  XO(31,232,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfme",    XO(31,232,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfme.", XO(31,232,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfme.",   XO(31,232,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfmeo",   XO(31,232,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfmeo.",  XO(31,232,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "mulld",   XO(31,233,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulld.",  XO(31,233,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulldo",  XO(31,233,1,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulldo.", XO(31,233,1,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "addme",   XO(31,234,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "ame",     XO(31,234,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addme.",  XO(31,234,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "ame.",    XO(31,234,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "addmeo",  XO(31,234,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "ameo",    XO(31,234,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "ameo.",   XO(31,234,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "mullw",   XO(31,235,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "muls",    XO(31,235,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "mullw.",  XO(31,235,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "muls.",   XO(31,235,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "mullwo",  XO(31,235,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulso",   XO(31,235,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "mullwo.", XO(31,235,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulso.",  XO(31,235,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "mtsrin",  X(31,242),	XRA_MASK,	PPC|B32,	{ RS, RB } },
+{ "mtsri",   X(31,242),	XRA_MASK,	POWER|B32,	{ RS, RB } },
+
+{ "dcbtst",  X(31,246),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "stbux",   X(31,247),	X_MASK,		PPC|POWER,	{ RS, RAS, RB } },
+
+{ "slliq",   XRC(31,248,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "slliq.",  XRC(31,248,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "doz",     XO(31,264,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "doz.",    XO(31,264,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "dozo",    XO(31,264,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "dozo.",   XO(31,264,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "add",     XO(31,266,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "cax",     XO(31,266,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "add.",    XO(31,266,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "cax.",    XO(31,266,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addo",    XO(31,266,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "caxo",    XO(31,266,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addo.",   XO(31,266,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "caxo.",   XO(31,266,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "lscbx",   XRC(31,277,0), X_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "lscbx.",  XRC(31,277,1), X_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "dcbt",    X(31,278),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lhzx",    X(31,279),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "icbt",    X(31,262),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "eqv",     XRC(31,284,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "eqv.",    XRC(31,284,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "tlbie",   X(31,306),	XRTRA_MASK,	PPC,		{ RB } },
+{ "tlbi",    X(31,306),	XRTRA_MASK,	POWER,		{ RB } },
+
+{ "eciwx",   X(31,310), X_MASK,		PPC,		{ RT, RA, RB } },
+
+{ "lhzux",   X(31,311),	X_MASK,		PPC|POWER,	{ RT, RAL, RB } },
+
+{ "xor",     XRC(31,316,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "xor.",    XRC(31,316,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "mfdcr",   X(31,323),	X_MASK,		PPC,		{ RT, SPR } },
+
+{ "div",     XO(31,331,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "div.",    XO(31,331,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divo",    XO(31,331,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divo.",   XO(31,331,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "mfmq",    XSPR(31,339,0), XSPR_MASK,	POWER|M601,	{ RT } },
+{ "mfxer",   XSPR(31,339,1), XSPR_MASK,	PPC|POWER,	{ RT } },
+{ "mfrtcu",  XSPR(31,339,4), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfrtcl",  XSPR(31,339,5), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfdec",   XSPR(31,339,6), XSPR_MASK, POWER|M601,	{ RT } },
+{ "mflr",    XSPR(31,339,8), XSPR_MASK,	PPC|POWER,	{ RT } },
+{ "mfctr",   XSPR(31,339,9), XSPR_MASK,	PPC|POWER,	{ RT } },
+{ "mftid",   XSPR(31,339,17), XSPR_MASK, POWER,		{ RT } },
+{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfdar",   XSPR(31,339,19), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfdec",   XSPR(31,339,22), XSPR_MASK, PPC,		{ RT } },
+{ "mfsdr0",  XSPR(31,339,24), XSPR_MASK, POWER,		{ RT } },
+{ "mfsdr1",  XSPR(31,339,25), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfsrr0",  XSPR(31,339,26), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfsrr1",  XSPR(31,339,27), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfsprg",  XSPR(31,339,272), XSPRG_MASK, PPC,		{ RT, SPRG } },
+{ "mfasr",   XSPR(31,339,280), XSPR_MASK, PPC|B64,	{ RT } },
+{ "mfear",   XSPR(31,339,282), XSPR_MASK, PPC,		{ RT } },
+{ "mfpvr",   XSPR(31,339,287), XSPR_MASK, PPC,		{ RT } },
+{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfspr",   X(31,339),	X_MASK,		PPC|POWER,	{ RT, SPR } },
+
+{ "lwax",    X(31,341),	X_MASK,		PPC|B64,	{ RT, RA, RB } },
+
+{ "lhax",    X(31,343),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "dccci",   X(31,454),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "abs",     XO(31,360,0,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "abs.",    XO(31,360,0,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "abso",    XO(31,360,1,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "abso.",   XO(31,360,1,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+
+{ "divs",    XO(31,363,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divs.",   XO(31,363,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divso",   XO(31,363,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divso.",  XO(31,363,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "tlbia",   X(31,370),	0xffffffff,	PPC,		{ 0 } },
+
+{ "mftbu",   XSPR(31,371,269), XSPR_MASK, PPC,		{ RT } },
+{ "mftb",    X(31,371),	X_MASK,		PPC,		{ RT, TBR } },
+
+{ "lwaux",   X(31,373),	X_MASK,		PPC|B64,	{ RT, RAL, RB } },
+
+{ "lhaux",   X(31,375),	X_MASK,		PPC|POWER,	{ RT, RAL, RB } },
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 04'
echo 'File patch-2.3.4 is continued in part 05'
echo 05 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 03 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 03; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/adb.c linux/arch/ppc/xmon/adb.c
--- v2.3.3/linux/arch/ppc/xmon/adb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/adb.c	Sat May 22 13:03:00 1999
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex	xmon_scanhex
+#define skipbl	xmon_skipbl
+
+#define ADB_B		(*(volatile unsigned char *)0xf3016000)
+#define ADB_SR		(*(volatile unsigned char *)0xf3017400)
+#define ADB_ACR		(*(volatile unsigned char *)0xf3017600)
+#define ADB_IFR		(*(volatile unsigned char *)0xf3017a00)
+
+static inline void eieio(void) { asm volatile ("eieio" : :); }
+
+#define N_ADB_LOG	1000
+struct adb_log {
+    unsigned char b;
+    unsigned char ifr;
+    unsigned char acr;
+    unsigned int time;
+} adb_log[N_ADB_LOG];
+int n_adb_log;
+
+void
+init_adb_log(void)
+{
+    adb_log[0].b = ADB_B;
+    adb_log[0].ifr = ADB_IFR;
+    adb_log[0].acr = ADB_ACR;
+    adb_log[0].time = get_dec();
+    n_adb_log = 0;
+}
+
+void
+dump_adb_log(void)
+{
+    unsigned t, t0;
+    struct adb_log *ap;
+    int i;
+
+    ap = adb_log;
+    t0 = ap->time;
+    for (i = 0; i <= n_adb_log; ++i, ++ap) {
+	t = t0 - ap->time;
+	printf("b=%x ifr=%x acr=%x at %d.%.7d\n", ap->b, ap->ifr, ap->acr,
+	       t / 1000000000, (t % 1000000000) / 100);
+    }
+}
+
+void
+adb_chklog(void)
+{
+    struct adb_log *ap = &adb_log[n_adb_log + 1];
+
+    ap->b = ADB_B;
+    ap->ifr = ADB_IFR;
+    ap->acr = ADB_ACR;
+    if (ap->b != ap[-1].b || (ap->ifr & 4) != (ap[-1].ifr & 4)
+	|| ap->acr != ap[-1].acr) {
+	ap->time = get_dec();
+	++n_adb_log;
+    }
+}
+
+int
+adb_bitwait(int bmask, int bval, int fmask, int fval)
+{
+    int i;
+    struct adb_log *ap;
+
+    for (i = 10000; i > 0; --i) {
+	adb_chklog();
+	ap = &adb_log[n_adb_log];
+	if ((ap->b & bmask) == bval && (ap->ifr & fmask) == fval)
+	    return 0;
+    }
+    return -1;
+}
+
+int
+adb_wait(void)
+{
+    if (adb_bitwait(0, 0, 4, 4) < 0) {
+	printf("adb: ready wait timeout\n");
+	return -1;
+    }
+    return 0;
+}
+
+void
+adb_readin(void)
+{
+    int i, j;
+    unsigned char d[64];
+
+    if (ADB_B & 8) {
+	printf("ADB_B: %x\n", ADB_B);
+	return;
+    }
+    i = 0;
+    adb_wait();
+    j = ADB_SR;
+    eieio();
+    ADB_B &= ~0x20;
+    eieio();
+    for (;;) {
+	if (adb_wait() < 0)
+	    break;
+	d[i++] = ADB_SR;
+	eieio();
+	if (ADB_B & 8)
+	    break;
+	ADB_B ^= 0x10;
+	eieio();
+    }
+    ADB_B |= 0x30;
+    if (adb_wait() == 0)
+	j = ADB_SR;
+    for (j = 0; j < i; ++j)
+	printf("%.2x ", d[j]);
+    printf("\n");
+}
+
+int
+adb_write(unsigned char *d, int i)
+{
+    int j;
+    unsigned x;
+
+    if ((ADB_B & 8) == 0) {
+	printf("r: ");
+	adb_readin();
+    }
+    for (;;) {
+	ADB_ACR = 0x1c;
+	eieio();
+	ADB_SR = d[0];
+	eieio();
+	ADB_B &= ~0x20;
+	eieio();
+	if (ADB_B & 8)
+	    break;
+	ADB_ACR = 0xc;
+	eieio();
+	ADB_B |= 0x20;
+	eieio();
+	adb_readin();
+    }
+    adb_wait();
+    for (j = 1; j < i; ++j) {
+	ADB_SR = d[j];
+	eieio();
+	ADB_B ^= 0x10;
+	eieio();
+	if (adb_wait() < 0)
+	    break;
+    }
+    ADB_ACR = 0xc;
+    eieio();
+    x = ADB_SR;
+    eieio();
+    ADB_B |= 0x30;
+    return j;
+}
+
+void
+adbcmds(void)
+{
+    char cmd;
+    unsigned rtcu, rtcl, dec, pdec, x;
+    int i, j;
+    unsigned char d[64];
+
+    cmd = skipbl();
+    switch (cmd) {
+    case 't':
+	for (;;) {
+	    rtcl = get_rtcl();
+	    rtcu = get_rtcu();
+	    dec = get_dec();
+	    printf("rtc u=%u l=%u dec=%x (%d = %d.%.7d)\n",
+		   rtcu, rtcl, dec, pdec - dec, (pdec - dec) / 1000000000,
+		   ((pdec - dec) % 1000000000) / 100);
+	    pdec = dec;
+	    if (cmd == 'x')
+		break;
+	    while (xmon_read(stdin, &cmd, 1) != 1)
+		;
+	}
+	break;
+    case 'r':
+	init_adb_log();
+	while (adb_bitwait(8, 0, 0, 0) == 0)
+	    adb_readin();
+	break;
+    case 'w':
+	i = 0;
+	while (scanhex(&x))
+	    d[i++] = x;
+	init_adb_log();
+	j = adb_write(d, i);
+	printf("sent %d bytes\n", j);
+	while (adb_bitwait(8, 0, 0, 0) == 0)
+	    adb_readin();
+	break;
+    case 'l':
+	dump_adb_log();
+	break;
+    }
+}
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/ansidecl.h linux/arch/ppc/xmon/ansidecl.h
--- v2.3.3/linux/arch/ppc/xmon/ansidecl.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/ansidecl.h	Sat May 22 13:03:00 1999
@@ -0,0 +1,141 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+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.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro	ANSI C definition	Traditional C definition
+   -----	---- - ----------	----------- - ----------
+   PTR		`void *'		`char *'
+   LONG_DOUBLE	`long double'		`double'
+   VOLATILE	`volatile'		`'
+   SIGNED	`signed'		`'
+   PTRCONST	`void *const'		`char *'
+   ANSI_PROTOTYPES  1			not defined
+
+   CONST is also defined, but is obsolete.  Just use const.
+
+   DEFUN (name, arglist, args)
+
+	Defines function NAME.
+
+	ARGLIST lists the arguments, separated by commas and enclosed in
+	parentheses.  ARGLIST becomes the argument list in traditional C.
+
+	ARGS list the arguments with their types.  It becomes a prototype in
+	ANSI C, and the type declarations in traditional C.  Arguments should
+	be separated with `AND'.  For functions with a variable number of
+	arguments, the last thing listed should be `DOTS'.
+
+   DEFUN_VOID (name)
+
+	Defines a function NAME, which takes no arguments.
+
+   obsolete --     EXFUN (name, (prototype))	-- obsolete.
+
+	Replaced by PARAMS.  Do not use; will disappear someday soon.
+	Was used in external function declarations.
+	In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+	parentheses).  In traditional C it is `NAME()'.
+	For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+    PARAMS ((args))
+
+	We could use the EXFUN macro to handle prototype declarations, but
+	the name is misleading and the result is ugly.  So we just define a
+	simple macro to handle the parameter lists, as in:
+
+	      static int foo PARAMS ((int, char));
+
+	This produces:  `static int foo();' or `static int foo (int, char);'
+
+	EXFUN would have done it like this:
+
+	      static int EXFUN (foo, (int, char));
+
+	but the function is not external...and it's hard to visually parse
+	the function name out of the mess.   EXFUN should be considered
+	obsolete; new code should be written to use PARAMS.
+
+    For example:
+	extern int printf PARAMS ((CONST char *format DOTS));
+	int DEFUN(fprintf, (stream, format),
+		  FILE *stream AND CONST char *format DOTS) { ... }
+	void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef	_ANSIDECL_H
+
+#define	_ANSIDECL_H	1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
+/* All known AIX compilers implement these things (but don't always
+   define __STDC__).  The RISC/OS MIPS compiler defines these things
+   in SVR4 mode, but does not define __STDC__.  */
+
+#define	PTR		void *
+#define	PTRCONST	void *CONST
+#define	LONG_DOUBLE	long double
+
+#define	AND		,
+#define	NOARGS		void
+#define	CONST		const
+#define	VOLATILE	volatile
+#define	SIGNED		signed
+#define	DOTS		, ...
+
+#define	EXFUN(name, proto)		name proto
+#define	DEFUN(name, arglist, args)	name(args)
+#define	DEFUN_VOID(name)		name(void)
+
+#define PROTO(type, name, arglist)	type name arglist
+#define PARAMS(paramlist)		paramlist
+#define ANSI_PROTOTYPES			1
+
+#else	/* Not ANSI C.  */
+
+#define	PTR		char *
+#define	PTRCONST	PTR
+#define	LONG_DOUBLE	double
+
+#define	AND		;
+#define	NOARGS
+#define	CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define	const
+#endif
+#define	VOLATILE
+#define	SIGNED
+#define	DOTS
+
+#define	EXFUN(name, proto)		name()
+#define	DEFUN(name, arglist, args)	name arglist args;
+#define	DEFUN_VOID(name)		name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist)		()
+
+#endif	/* ANSI C.  */
+
+#endif	/* ansidecl.h	*/
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/nonstdio.h linux/arch/ppc/xmon/nonstdio.h
--- v2.3.3/linux/arch/ppc/xmon/nonstdio.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/nonstdio.h	Sat May 22 13:03:00 1999
@@ -0,0 +1,22 @@
+typedef int	FILE;
+extern FILE *xmon_stdin, *xmon_stdout;
+#define EOF	(-1)
+#define stdin	xmon_stdin
+#define stdout	xmon_stdout
+#define printf	xmon_printf
+#define fprintf	xmon_fprintf
+#define fputs	xmon_fputs
+#define fgets	xmon_fgets
+#define putchar	xmon_putchar
+#define getchar	xmon_getchar
+#define putc	xmon_putc
+#define getc	xmon_getc
+#define fopen(n, m)	NULL
+#define fflush(f)	do {} while (0)
+#define fclose(f)	do {} while (0)
+extern char *fgets(char *, int, void *);
+extern void xmon_printf(const char *, ...);
+extern void xmon_fprintf(void *, const char *, ...);
+extern void xmon_sprintf(char *, const char *, ...);
+
+#define perror(s)	printf("%s: no files!\n", (s))
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/ppc-dis.c linux/arch/ppc/xmon/ppc-dis.c
--- v2.3.3/linux/arch/ppc/xmon/ppc-dis.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/ppc-dis.c	Sat May 22 13:03:00 1999
@@ -0,0 +1,190 @@
+/* ppc-dis.c -- Disassemble PowerPC instructions
+   Copyright 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+2, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "nonstdio.h"
+#include "ansidecl.h"
+#include "ppc.h"
+
+static int print_insn_powerpc PARAMS ((FILE *, unsigned long insn,
+				       unsigned memaddr, int dialect));
+
+extern void print_address PARAMS((unsigned memaddr));
+
+/* Print a big endian PowerPC instruction.  For convenience, also
+   disassemble instructions supported by the Motorola PowerPC 601.  */
+
+int
+print_insn_big_powerpc (FILE *out, unsigned long insn, unsigned memaddr)
+{
+  return print_insn_powerpc (out, insn, memaddr,
+			     PPC_OPCODE_PPC | PPC_OPCODE_601);
+}
+
+/* Print a PowerPC or POWER instruction.  */
+
+static int
+print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
+		    int dialect)
+{
+  const struct powerpc_opcode *opcode;
+  const struct powerpc_opcode *opcode_end;
+  unsigned long op;
+
+  /* Get the major opcode of the instruction.  */
+  op = PPC_OP (insn);
+
+  /* Find the first match in the opcode table.  We could speed this up
+     a bit by doing a binary search on the major opcode.  */
+  opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+  for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
+    {
+      unsigned long table_op;
+      const unsigned char *opindex;
+      const struct powerpc_operand *operand;
+      int invalid;
+      int need_comma;
+      int need_paren;
+
+      table_op = PPC_OP (opcode->opcode);
+      if (op < table_op)
+		break;
+      if (op > table_op)
+		continue;
+
+      if ((insn & opcode->mask) != opcode->opcode
+	  || (opcode->flags & dialect) == 0)
+		continue;
+
+      /* Make two passes over the operands.  First see if any of them
+		 have extraction functions, and, if they do, make sure the
+		 instruction is valid.  */
+      invalid = 0;
+      for (opindex = opcode->operands; *opindex != 0; opindex++)
+		{
+		  operand = powerpc_operands + *opindex;
+		  if (operand->extract)
+		    (*operand->extract) (insn, &invalid);
+		}
+      if (invalid)
+		continue;
+
+      /* The instruction is valid.  */
+      fprintf(out, "%s", opcode->name);
+      if (opcode->operands[0] != 0)
+		fprintf(out, "\t");
+
+      /* Now extract and print the operands.  */
+      need_comma = 0;
+      need_paren = 0;
+      for (opindex = opcode->operands; *opindex != 0; opindex++)
+		{
+		  long value;
+
+		  operand = powerpc_operands + *opindex;
+
+		  /* Operands that are marked FAKE are simply ignored.  We
+		     already made sure that the extract function considered
+		     the instruction to be valid.  */
+		  if ((operand->flags & PPC_OPERAND_FAKE) != 0)
+		    continue;
+
+		  /* Extract the value from the instruction.  */
+		  if (operand->extract)
+		    value = (*operand->extract) (insn, (int *) 0);
+		  else
+		    {
+		      value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+		      if ((operand->flags & PPC_OPERAND_SIGNED) != 0
+			  && (value & (1 << (operand->bits - 1))) != 0)
+			value -= 1 << operand->bits;
+		    }
+
+		  /* If the operand is optional, and the value is zero, don't
+		     print anything.  */
+		  if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+		      && (operand->flags & PPC_OPERAND_NEXT) == 0
+		      && value == 0)
+		    continue;
+
+		  if (need_comma)
+		    {
+		      fprintf(out, ",");
+		      need_comma = 0;
+		    }
+
+		  /* Print the operand as directed by the flags.  */
+		  if ((operand->flags & PPC_OPERAND_GPR) != 0)
+		    fprintf(out, "r%ld", value);
+		  else if ((operand->flags & PPC_OPERAND_FPR) != 0)
+		    fprintf(out, "f%ld", value);
+		  else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
+		    print_address (memaddr + value);
+		  else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+		    print_address (value & 0xffffffff);
+		  else if ((operand->flags & PPC_OPERAND_CR) == 0
+			   || (dialect & PPC_OPCODE_PPC) == 0)
+		    fprintf(out, "%ld", value);
+		  else
+		    {
+		      if (operand->bits == 3)
+				fprintf(out, "cr%d", value);
+		      else
+			{
+			  static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+			  int cr;
+			  int cc;
+
+			  cr = value >> 2;
+			  if (cr != 0)
+			    fprintf(out, "4*cr%d", cr);
+			  cc = value & 3;
+			  if (cc != 0)
+			    {
+			      if (cr != 0)
+					fprintf(out, "+");
+			      fprintf(out, "%s", cbnames[cc]);
+			    }
+			}
+	    }
+
+	  if (need_paren)
+	    {
+	      fprintf(out, ")");
+	      need_paren = 0;
+	    }
+
+	  if ((operand->flags & PPC_OPERAND_PARENS) == 0)
+	    need_comma = 1;
+	  else
+	    {
+	      fprintf(out, "(");
+	      need_paren = 1;
+	    }
+	}
+
+      /* We have found and printed an instruction; return.  */
+      return 4;
+    }
+
+  /* We could not find a match.  */
+  fprintf(out, ".long 0x%lx", insn);
+
+  return 4;
+}
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/ppc-opc.c linux/arch/ppc/xmon/ppc-opc.c
--- v2.3.3/linux/arch/ppc/xmon/ppc-opc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/ppc-opc.c	Sat May 22 13:03:00 1999
@@ -0,0 +1,2816 @@
+/* ppc-opc.c -- PowerPC opcode list
+   Copyright 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+2, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <linux/posix_types.h>
+#include "ansidecl.h"
+#include "ppc.h"
+
+/* This file holds the PowerPC opcode table.  The opcode table
+   includes almost all of the extended instruction mnemonics.  This
+   permits the disassembler to use them, and simplifies the assembler
+   logic, at the cost of increasing the table size.  The table is
+   strictly constant data, so the compiler should be able to put it in
+   the .text section.
+
+   This file also holds the operand table.  All knowledge about
+   inserting operands into instructions and vice-versa is kept in this
+   file.  */
+
+/* Local insertion and extraction functions.  */
+
+static unsigned long insert_bat PARAMS ((unsigned long, long, const char **));
+static long extract_bat PARAMS ((unsigned long, int *));
+static unsigned long insert_bba PARAMS ((unsigned long, long, const char **));
+static long extract_bba PARAMS ((unsigned long, int *));
+static unsigned long insert_bd PARAMS ((unsigned long, long, const char **));
+static long extract_bd PARAMS ((unsigned long, int *));
+static unsigned long insert_bdm PARAMS ((unsigned long, long, const char **));
+static long extract_bdm PARAMS ((unsigned long, int *));
+static unsigned long insert_bdp PARAMS ((unsigned long, long, const char **));
+static long extract_bdp PARAMS ((unsigned long, int *));
+static unsigned long insert_bo PARAMS ((unsigned long, long, const char **));
+static long extract_bo PARAMS ((unsigned long, int *));
+static unsigned long insert_boe PARAMS ((unsigned long, long, const char **));
+static long extract_boe PARAMS ((unsigned long, int *));
+static unsigned long insert_ds PARAMS ((unsigned long, long, const char **));
+static long extract_ds PARAMS ((unsigned long, int *));
+static unsigned long insert_li PARAMS ((unsigned long, long, const char **));
+static long extract_li PARAMS ((unsigned long, int *));
+static unsigned long insert_mbe PARAMS ((unsigned long, long, const char **));
+static long extract_mbe PARAMS ((unsigned long, int *));
+static unsigned long insert_mb6 PARAMS ((unsigned long, long, const char **));
+static long extract_mb6 PARAMS ((unsigned long, int *));
+static unsigned long insert_nb PARAMS ((unsigned long, long, const char **));
+static long extract_nb PARAMS ((unsigned long, int *));
+static unsigned long insert_nsi PARAMS ((unsigned long, long, const char **));
+static long extract_nsi PARAMS ((unsigned long, int *));
+static unsigned long insert_ral PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_ram PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_ras PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_rbs PARAMS ((unsigned long, long, const char **));
+static long extract_rbs PARAMS ((unsigned long, int *));
+static unsigned long insert_sh6 PARAMS ((unsigned long, long, const char **));
+static long extract_sh6 PARAMS ((unsigned long, int *));
+static unsigned long insert_spr PARAMS ((unsigned long, long, const char **));
+static long extract_spr PARAMS ((unsigned long, int *));
+static unsigned long insert_tbr PARAMS ((unsigned long, long, const char **));
+static long extract_tbr PARAMS ((unsigned long, int *));
+
+/* The operands table.
+
+   The fields are bits, shift, signed, insert, extract, flags.  */
+
+const struct powerpc_operand powerpc_operands[] =
+{
+  /* The zero index is used to indicate the end of the list of
+     operands.  */
+#define UNUSED (0)
+  { 0, 0, 0, 0, 0 },
+
+  /* The BA field in an XL form instruction.  */
+#define BA (1)
+#define BA_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_CR },
+
+  /* The BA field in an XL form instruction when it must be the same
+     as the BT field in the same instruction.  */
+#define BAT (2)
+  { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE },
+
+  /* The BB field in an XL form instruction.  */
+#define BB (3)
+#define BB_MASK (0x1f << 11)
+  { 5, 11, 0, 0, PPC_OPERAND_CR },
+
+  /* The BB field in an XL form instruction when it must be the same
+     as the BA field in the same instruction.  */
+#define BBA (4)
+  { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE },
+
+  /* The BD field in a B form instruction.  The lower two bits are
+     forced to zero.  */
+#define BD (5)
+  { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when absolute addressing is
+     used.  */
+#define BDA (6)
+  { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the - modifier is used.
+     This sets the y bit of the BO field appropriately.  */
+#define BDM (7)
+  { 16, 0, insert_bdm, extract_bdm,
+      PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the - modifier is used
+     and absolute address is used.  */
+#define BDMA (8)
+  { 16, 0, insert_bdm, extract_bdm,
+      PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the + modifier is used.
+     This sets the y bit of the BO field appropriately.  */
+#define BDP (9)
+  { 16, 0, insert_bdp, extract_bdp,
+      PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the + modifier is used
+     and absolute addressing is used.  */
+#define BDPA (10)
+  { 16, 0, insert_bdp, extract_bdp,
+      PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The BF field in an X or XL form instruction.  */
+#define BF (11)
+  { 3, 23, 0, 0, PPC_OPERAND_CR },
+
+  /* An optional BF field.  This is used for comparison instructions,
+     in which an omitted BF field is taken as zero.  */
+#define OBF (12)
+  { 3, 23, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+  /* The BFA field in an X or XL form instruction.  */
+#define BFA (13)
+  { 3, 18, 0, 0, PPC_OPERAND_CR },
+
+  /* The BI field in a B form or XL form instruction.  */
+#define BI (14)
+#define BI_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_CR },
+
+  /* The BO field in a B form instruction.  Certain values are
+     illegal.  */
+#define BO (15)
+#define BO_MASK (0x1f << 21)
+  { 5, 21, insert_bo, extract_bo, 0 },
+
+  /* The BO field in a B form instruction when the + or - modifier is
+     used.  This is like the BO field, but it must be even.  */
+#define BOE (16)
+  { 5, 21, insert_boe, extract_boe, 0 },
+
+  /* The BT field in an X or XL form instruction.  */
+#define BT (17)
+  { 5, 21, 0, 0, PPC_OPERAND_CR },
+
+  /* The condition register number portion of the BI field in a B form
+     or XL form instruction.  This is used for the extended
+     conditional branch mnemonics, which set the lower two bits of the
+     BI field.  This field is optional.  */
+#define CR (18)
+  { 3, 18, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+  /* The D field in a D form instruction.  This is a displacement off
+     a register, and implies that the next operand is a register in
+     parentheses.  */
+#define D (19)
+  { 16, 0, 0, 0, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+  /* The DS field in a DS form instruction.  This is like D, but the
+     lower two bits are forced to zero.  */
+#define DS (20)
+  { 16, 0, insert_ds, extract_ds, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+  /* The FL1 field in a POWER SC form instruction.  */
+#define FL1 (21)
+  { 4, 12, 0, 0, 0 },
+
+  /* The FL2 field in a POWER SC form instruction.  */
+#define FL2 (22)
+  { 3, 2, 0, 0, 0 },
+
+  /* The FLM field in an XFL form instruction.  */
+#define FLM (23)
+  { 8, 17, 0, 0, 0 },
+
+  /* The FRA field in an X or A form instruction.  */
+#define FRA (24)
+#define FRA_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FRB field in an X or A form instruction.  */
+#define FRB (25)
+#define FRB_MASK (0x1f << 11)
+  { 5, 11, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FRC field in an A form instruction.  */
+#define FRC (26)
+#define FRC_MASK (0x1f << 6)
+  { 5, 6, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FRS field in an X form instruction or the FRT field in a D, X
+     or A form instruction.  */
+#define FRS (27)
+#define FRT (FRS)
+  { 5, 21, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FXM field in an XFX instruction.  */
+#define FXM (28)
+#define FXM_MASK (0xff << 12)
+  { 8, 12, 0, 0, 0 },
+
+  /* The L field in a D or X form instruction.  */
+#define L (29)
+  { 1, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+
+  /* The LEV field in a POWER SC form instruction.  */
+#define LEV (30)
+  { 7, 5, 0, 0, 0 },
+
+  /* The LI field in an I form instruction.  The lower two bits are
+     forced to zero.  */
+#define LI (31)
+  { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The LI field in an I form instruction when used as an absolute
+     address.  */
+#define LIA (32)
+  { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The MB field in an M form instruction.  */
+#define MB (33)
+#define MB_MASK (0x1f << 6)
+  { 5, 6, 0, 0, 0 },
+
+  /* The ME field in an M form instruction.  */
+#define ME (34)
+#define ME_MASK (0x1f << 1)
+  { 5, 1, 0, 0, 0 },
+
+  /* The MB and ME fields in an M form instruction expressed a single
+     operand which is a bitmask indicating which bits to select.  This
+     is a two operand form using PPC_OPERAND_NEXT.  See the
+     description in opcode/ppc.h for what this means.  */
+#define MBE (35)
+  { 5, 6, 0, 0, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+  { 32, 0, insert_mbe, extract_mbe, 0 },
+
+  /* The MB or ME field in an MD or MDS form instruction.  The high
+     bit is wrapped to the low end.  */
+#define MB6 (37)
+#define ME6 (MB6)
+#define MB6_MASK (0x3f << 5)
+  { 6, 5, insert_mb6, extract_mb6, 0 },
+
+  /* The NB field in an X form instruction.  The value 32 is stored as
+     0.  */
+#define NB (38)
+  { 6, 11, insert_nb, extract_nb, 0 },
+
+  /* The NSI field in a D form instruction.  This is the same as the
+     SI field, only negated.  */
+#define NSI (39)
+  { 16, 0, insert_nsi, extract_nsi,
+      PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
+
+  /* The RA field in an D, DS, X, XO, M, or MDS form instruction.  */
+#define RA (40)
+#define RA_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_GPR },
+
+  /* The RA field in a D or X form instruction which is an updating
+     load, which means that the RA field may not be zero and may not
+     equal the RT field.  */
+#define RAL (41)
+  { 5, 16, insert_ral, 0, PPC_OPERAND_GPR },
+
+  /* The RA field in an lmw instruction, which has special value
+     restrictions.  */
+#define RAM (42)
+  { 5, 16, insert_ram, 0, PPC_OPERAND_GPR },
+
+  /* The RA field in a D or X form instruction which is an updating
+     store or an updating floating point load, which means that the RA
+     field may not be zero.  */
+#define RAS (43)
+  { 5, 16, insert_ras, 0, PPC_OPERAND_GPR },
+
+  /* The RB field in an X, XO, M, or MDS form instruction.  */
+#define RB (44)
+#define RB_MASK (0x1f << 11)
+  { 5, 11, 0, 0, PPC_OPERAND_GPR },
+
+  /* The RB field in an X form instruction when it must be the same as
+     the RS field in the instruction.  This is used for extended
+     mnemonics like mr.  */
+#define RBS (45)
+  { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE },
+
+  /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form
+     instruction or the RT field in a D, DS, X, XFX or XO form
+     instruction.  */
+#define RS (46)
+#define RT (RS)
+#define RT_MASK (0x1f << 21)
+  { 5, 21, 0, 0, PPC_OPERAND_GPR },
+
+  /* The SH field in an X or M form instruction.  */
+#define SH (47)
+#define SH_MASK (0x1f << 11)
+  { 5, 11, 0, 0, 0 },
+
+  /* The SH field in an MD form instruction.  This is split.  */
+#define SH6 (48)
+#define SH6_MASK ((0x1f << 11) | (1 << 1))
+  { 6, 1, insert_sh6, extract_sh6, 0 },
+
+  /* The SI field in a D form instruction.  */
+#define SI (49)
+  { 16, 0, 0, 0, PPC_OPERAND_SIGNED },
+
+  /* The SI field in a D form instruction when we accept a wide range
+     of positive values.  */
+#define SISIGNOPT (50)
+  { 16, 0, 0, 0, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+
+  /* The SPR field in an XFX form instruction.  This is flipped--the
+     lower 5 bits are stored in the upper 5 and vice- versa.  */
+#define SPR (51)
+#define SPR_MASK (0x3ff << 11)
+  { 10, 11, insert_spr, extract_spr, 0 },
+
+  /* The BAT index number in an XFX form m[ft]ibat[lu] instruction.  */
+#define SPRBAT (52)
+#define SPRBAT_MASK (0x3 << 17)
+  { 2, 17, 0, 0, 0 },
+
+  /* The SPRG register number in an XFX form m[ft]sprg instruction.  */
+#define SPRG (53)
+#define SPRG_MASK (0x3 << 16)
+  { 2, 16, 0, 0, 0 },
+
+  /* The SR field in an X form instruction.  */
+#define SR (54)
+  { 4, 16, 0, 0, 0 },
+
+  /* The SV field in a POWER SC form instruction.  */
+#define SV (55)
+  { 14, 2, 0, 0, 0 },
+
+  /* The TBR field in an XFX form instruction.  This is like the SPR
+     field, but it is optional.  */
+#define TBR (56)
+  { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
+
+  /* The TO field in a D or X form instruction.  */
+#define TO (57)
+#define TO_MASK (0x1f << 21)
+  { 5, 21, 0, 0, 0 },
+
+  /* The U field in an X form instruction.  */
+#define U (58)
+  { 4, 12, 0, 0, 0 },
+
+  /* The UI field in a D form instruction.  */
+#define UI (59)
+  { 16, 0, 0, 0, 0 },
+};
+
+/* The functions used to insert and extract complicated operands.  */
+
+/* The BA field in an XL form instruction when it must be the same as
+   the BT field in the same instruction.  This operand is marked FAKE.
+   The insertion function just copies the BT field into the BA field,
+   and the extraction function just checks that the fields are the
+   same.  */
+
+/*ARGSUSED*/
+static unsigned long 
+insert_bat (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (((insn >> 21) & 0x1f) << 16);
+}
+
+static long
+extract_bat (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
+    *invalid = 1;
+  return 0;
+}
+
+/* The BB field in an XL form instruction when it must be the same as
+   the BA field in the same instruction.  This operand is marked FAKE.
+   The insertion function just copies the BA field into the BB field,
+   and the extraction function just checks that the fields are the
+   same.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bba (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (((insn >> 16) & 0x1f) << 11);
+}
+
+static long
+extract_bba (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f))
+    *invalid = 1;
+  return 0;
+}
+
+/* The BD field in a B form instruction.  The lower two bits are
+   forced to zero.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bd (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (value & 0xfffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_bd (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* The BD field in a B form instruction when the - modifier is used.
+   This modifier means that the branch is not expected to be taken.
+   We must set the y bit of the BO field to 1 if the offset is
+   negative.  When extracting, we require that the y bit be 1 and that
+   the offset be positive, since if the y bit is 0 we just want to
+   print the normal form of the instruction.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bdm (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if ((value & 0x8000) != 0)
+    insn |= 1 << 21;
+  return insn | (value & 0xfffc);
+}
+
+static long
+extract_bdm (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn & (1 << 21)) == 0
+	  || (insn & (1 << 15)) == 0))
+    *invalid = 1;
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* The BD field in a B form instruction when the + modifier is used.
+   This is like BDM, above, except that the branch is expected to be
+   taken.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bdp (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if ((value & 0x8000) == 0)
+    insn |= 1 << 21;
+  return insn | (value & 0xfffc);
+}
+
+static long
+extract_bdp (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn & (1 << 21)) == 0
+	  || (insn & (1 << 15)) != 0))
+    *invalid = 1;
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* Check for legal values of a BO field.  */
+
+static int
+valid_bo (value)
+     long value;
+{
+  /* Certain encodings have bits that are required to be zero.  These
+     are (z must be zero, y may be anything):
+         001zy
+	 011zy
+	 1z00y
+	 1z01y
+	 1z1zz
+     */
+  switch (value & 0x14)
+    {
+    default:
+    case 0:
+      return 1;
+    case 0x4:
+      return (value & 0x2) == 0;
+    case 0x10:
+      return (value & 0x8) == 0;
+    case 0x14:
+      return value == 0x14;
+    }
+}
+
+/* The BO field in a B form instruction.  Warn about attempts to set
+   the field to an illegal value.  */
+
+static unsigned long
+insert_bo (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (errmsg != (const char **) NULL
+      && ! valid_bo (value))
+    *errmsg = "invalid conditional option";
+  return insn | ((value & 0x1f) << 21);
+}
+
+static long
+extract_bo (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long value;
+
+  value = (insn >> 21) & 0x1f;
+  if (invalid != (int *) NULL
+      && ! valid_bo (value))
+    *invalid = 1;
+  return value;
+}
+
+/* The BO field in a B form instruction when the + or - modifier is
+   used.  This is like the BO field, but it must be even.  When
+   extracting it, we force it to be even.  */
+
+static unsigned long
+insert_boe (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (errmsg != (const char **) NULL)
+    {
+      if (! valid_bo (value))
+	*errmsg = "invalid conditional option";
+      else if ((value & 1) != 0)
+	*errmsg = "attempt to set y bit when using + or - modifier";
+    }
+  return insn | ((value & 0x1f) << 21);
+}
+
+static long
+extract_boe (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long value;
+
+  value = (insn >> 21) & 0x1f;
+  if (invalid != (int *) NULL
+      && ! valid_bo (value))
+    *invalid = 1;
+  return value & 0x1e;
+}
+
+/* The DS field in a DS form instruction.  This is like D, but the
+   lower two bits are forced to zero.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_ds (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (value & 0xfffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_ds (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* The LI field in an I form instruction.  The lower two bits are
+   forced to zero.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_li (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (value & 0x3fffffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_li (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if ((insn & 0x2000000) != 0)
+    return (insn & 0x3fffffc) - 0x4000000;
+  else
+    return insn & 0x3fffffc;
+}
+
+/* The MB and ME fields in an M form instruction expressed as a single
+   operand which is itself a bitmask.  The extraction function always
+   marks it as invalid, since we never want to recognize an
+   instruction which uses a field of this type.  */
+
+static unsigned long
+insert_mbe (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  unsigned long uval;
+  int mb, me;
+
+  uval = value;
+
+  if (uval == 0)
+    {
+      if (errmsg != (const char **) NULL)
+	*errmsg = "illegal bitmask";
+      return insn;
+    }
+
+  me = 31;
+  while ((uval & 1) == 0)
+    {
+      uval >>= 1;
+      --me;
+    }
+
+  mb = me;
+  uval >>= 1;
+  while ((uval & 1) != 0)
+    {
+      uval >>= 1;
+      --mb;
+    }
+
+  if (uval != 0)
+    {
+      if (errmsg != (const char **) NULL)
+	*errmsg = "illegal bitmask";
+    }
+
+  return insn | (mb << 6) | (me << 1);
+}
+
+static long
+extract_mbe (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long ret;
+  int mb, me;
+  int i;
+
+  if (invalid != (int *) NULL)
+    *invalid = 1;
+
+  ret = 0;
+  mb = (insn >> 6) & 0x1f;
+  me = (insn >> 1) & 0x1f;
+  for (i = mb; i < me; i++)
+    ret |= 1 << (31 - i);
+  return ret;
+}
+
+/* The MB or ME field in an MD or MDS form instruction.  The high bit
+   is wrapped to the low end.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_mb6 (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((value & 0x1f) << 6) | (value & 0x20);
+}
+
+/*ARGSUSED*/
+static long
+extract_mb6 (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  return ((insn >> 6) & 0x1f) | (insn & 0x20);
+}
+
+/* The NB field in an X form instruction.  The value 32 is stored as
+   0.  */
+
+static unsigned long
+insert_nb (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value < 0 || value > 32)
+    *errmsg = "value out of range";
+  if (value == 32)
+    value = 0;
+  return insn | ((value & 0x1f) << 11);
+}
+
+/*ARGSUSED*/
+static long
+extract_nb (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long ret;
+
+  ret = (insn >> 11) & 0x1f;
+  if (ret == 0)
+    ret = 32;
+  return ret;
+}
+
+/* The NSI field in a D form instruction.  This is the same as the SI
+   field, only negated.  The extraction function always marks it as
+   invalid, since we never want to recognize an instruction which uses
+   a field of this type.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_nsi (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((- value) & 0xffff);
+}
+
+static long
+extract_nsi (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL)
+    *invalid = 1;
+  if ((insn & 0x8000) != 0)
+    return - ((insn & 0xffff) - 0x10000);
+  else
+    return - (insn & 0xffff);
+}
+
+/* The RA field in a D or X form instruction which is an updating
+   load, which means that the RA field may not be zero and may not
+   equal the RT field.  */
+
+static unsigned long
+insert_ral (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value == 0
+      || value == ((insn >> 21) & 0x1f))
+    *errmsg = "invalid register operand when updating";
+  return insn | ((value & 0x1f) << 16);
+}
+
+/* The RA field in an lmw instruction, which has special value
+   restrictions.  */
+
+static unsigned long
+insert_ram (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value >= ((insn >> 21) & 0x1f))
+    *errmsg = "index register in load range";
+  return insn | ((value & 0x1f) << 16);
+}
+
+/* The RA field in a D or X form instruction which is an updating
+   store or an updating floating point load, which means that the RA
+   field may not be zero.  */
+
+static unsigned long
+insert_ras (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value == 0)
+    *errmsg = "invalid register operand when updating";
+  return insn | ((value & 0x1f) << 16);
+}
+
+/* The RB field in an X form instruction when it must be the same as
+   the RS field in the instruction.  This is used for extended
+   mnemonics like mr.  This operand is marked FAKE.  The insertion
+   function just copies the BT field into the BA field, and the
+   extraction function just checks that the fields are the same.  */
+
+/*ARGSUSED*/
+static unsigned long 
+insert_rbs (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (((insn >> 21) & 0x1f) << 11);
+}
+
+static long
+extract_rbs (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f))
+    *invalid = 1;
+  return 0;
+}
+
+/* The SH field in an MD form instruction.  This is split.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_sh6 (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
+}
+
+/*ARGSUSED*/
+static long
+extract_sh6 (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
+}
+
+/* The SPR field in an XFX form instruction.  This is flipped--the
+   lower 5 bits are stored in the upper 5 and vice- versa.  */
+
+static unsigned long
+insert_spr (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+}
+
+static long
+extract_spr (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+}
+
+/* The TBR field in an XFX instruction.  This is just like SPR, but it
+   is optional.  When TBR is omitted, it must be inserted as 268 (the
+   magic number of the TB register).  These functions treat 0
+   (indicating an omitted optional operand) as 268.  This means that
+   ``mftb 4,0'' is not handled correctly.  This does not matter very
+   much, since the architecture manual does not define mftb as
+   accepting any values other than 268 or 269.  */
+
+#define TB (268)
+
+static unsigned long
+insert_tbr (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value == 0)
+    value = TB;
+  return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+}
+
+static long
+extract_tbr (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long ret;
+
+  ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+  if (ret == TB)
+    ret = 0;
+  return ret;
+}
+
+/* Macros used to form opcodes.  */
+
+/* The main opcode.  */
+#define OP(x) (((x) & 0x3f) << 26)
+#define OP_MASK OP (0x3f)
+
+/* The main opcode combined with a trap code in the TO field of a D
+   form instruction.  Used for extended mnemonics for the trap
+   instructions.  */
+#define OPTO(x,to) (OP (x) | (((to) & 0x1f) << 21))
+#define OPTO_MASK (OP_MASK | TO_MASK)
+
+/* The main opcode combined with a comparison size bit in the L field
+   of a D form or X form instruction.  Used for extended mnemonics for
+   the comparison instructions.  */
+#define OPL(x,l) (OP (x) | (((l) & 1) << 21))
+#define OPL_MASK OPL (0x3f,1)
+
+/* An A form instruction.  */
+#define A(op, xop, rc) (OP (op) | (((xop) & 0x1f) << 1) | ((rc) & 1))
+#define A_MASK A (0x3f, 0x1f, 1)
+
+/* An A_MASK with the FRB field fixed.  */
+#define AFRB_MASK (A_MASK | FRB_MASK)
+
+/* An A_MASK with the FRC field fixed.  */
+#define AFRC_MASK (A_MASK | FRC_MASK)
+
+/* An A_MASK with the FRA and FRC fields fixed.  */
+#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
+
+/* A B form instruction.  */
+#define B(op, aa, lk) (OP (op) | (((aa) & 1) << 1) | ((lk) & 1))
+#define B_MASK B (0x3f, 1, 1)
+
+/* A B form instruction setting the BO field.  */
+#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | (((bo) & 0x1f) << 21))
+#define BBO_MASK BBO (0x3f, 0x1f, 1, 1)
+
+/* A BBO_MASK with the y bit of the BO field removed.  This permits
+   matching a conditional branch regardless of the setting of the y
+   bit.  */
+#define Y_MASK (1 << 21)
+#define BBOY_MASK (BBO_MASK &~ Y_MASK)
+
+/* A B form instruction setting the BO field and the condition bits of
+   the BI field.  */
+#define BBOCB(op, bo, cb, aa, lk) \
+  (BBO ((op), (bo), (aa), (lk)) | (((cb) & 0x3) << 16))
+#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1)
+
+/* A BBOCB_MASK with the y bit of the BO field removed.  */
+#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK)
+
+/* A BBOYCB_MASK in which the BI field is fixed.  */
+#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK)
+
+/* The main opcode mask with the RA field clear.  */
+#define DRA_MASK (OP_MASK | RA_MASK)
+
+/* A DS form instruction.  */
+#define DSO(op, xop) (OP (op) | ((xop) & 0x3))
+#define DS_MASK DSO (0x3f, 3)
+
+/* An M form instruction.  */
+#define M(op, rc) (OP (op) | ((rc) & 1))
+#define M_MASK M (0x3f, 1)
+
+/* An M form instruction with the ME field specified.  */
+#define MME(op, me, rc) (M ((op), (rc)) | (((me) & 0x1f) << 1))
+
+/* An M_MASK with the MB and ME fields fixed.  */
+#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK)
+
+/* An M_MASK with the SH and ME fields fixed.  */
+#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK)
+
+/* An MD form instruction.  */
+#define MD(op, xop, rc) (OP (op) | (((xop) & 0x7) << 2) | ((rc) & 1))
+#define MD_MASK MD (0x3f, 0x7, 1)
+
+/* An MD_MASK with the MB field fixed.  */
+#define MDMB_MASK (MD_MASK | MB6_MASK)
+
+/* An MD_MASK with the SH field fixed.  */
+#define MDSH_MASK (MD_MASK | SH6_MASK)
+
+/* An MDS form instruction.  */
+#define MDS(op, xop, rc) (OP (op) | (((xop) & 0xf) << 1) | ((rc) & 1))
+#define MDS_MASK MDS (0x3f, 0xf, 1)
+
+/* An MDS_MASK with the MB field fixed.  */
+#define MDSMB_MASK (MDS_MASK | MB6_MASK)
+
+/* An SC form instruction.  */
+#define SC(op, sa, lk) (OP (op) | (((sa) & 1) << 1) | ((lk) & 1))
+#define SC_MASK (OP_MASK | (0x3ff << 16) | (1 << 1) | 1)
+
+/* An X form instruction.  */
+#define X(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An X form instruction with the RC bit specified.  */
+#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
+
+/* The mask for an X form instruction.  */
+#define X_MASK XRC (0x3f, 0x3ff, 1)
+
+/* An X_MASK with the RA field fixed.  */
+#define XRA_MASK (X_MASK | RA_MASK)
+
+/* An X_MASK with the RB field fixed.  */
+#define XRB_MASK (X_MASK | RB_MASK)
+
+/* An X_MASK with the RT field fixed.  */
+#define XRT_MASK (X_MASK | RT_MASK)
+
+/* An X_MASK with the RA and RB fields fixed.  */
+#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
+
+/* An X_MASK with the RT and RA fields fixed.  */
+#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK)
+
+/* An X form comparison instruction.  */
+#define XCMPL(op, xop, l) (X ((op), (xop)) | (((l) & 1) << 21))
+
+/* The mask for an X form comparison instruction.  */
+#define XCMP_MASK (X_MASK | (1 << 22))
+
+/* The mask for an X form comparison instruction with the L field
+   fixed.  */
+#define XCMPL_MASK (XCMP_MASK | (1 << 21))
+
+/* An X form trap instruction with the TO field specified.  */
+#define XTO(op, xop, to) (X ((op), (xop)) | (((to) & 0x1f) << 21))
+#define XTO_MASK (X_MASK | TO_MASK)
+
+/* An XFL form instruction.  */
+#define XFL(op, xop, rc) (OP (op) | (((xop) & 0x3ff) << 1) | ((rc) & 1))
+#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (1 << 25) | (1 << 16))
+
+/* An XL form instruction with the LK field set to 0.  */
+#define XL(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An XL form instruction which uses the LK field.  */
+#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1))
+
+/* The mask for an XL form instruction.  */
+#define XL_MASK XLLK (0x3f, 0x3ff, 1)
+
+/* An XL form instruction which explicitly sets the BO field.  */
+#define XLO(op, bo, xop, lk) \
+  (XLLK ((op), (xop), (lk)) | (((bo) & 0x1f) << 21))
+#define XLO_MASK (XL_MASK | BO_MASK)
+
+/* An XL form instruction which explicitly sets the y bit of the BO
+   field.  */
+#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | (((y) & 1) << 21))
+#define XLYLK_MASK (XL_MASK | Y_MASK)
+
+/* An XL form instruction which sets the BO field and the condition
+   bits of the BI field.  */
+#define XLOCB(op, bo, cb, xop, lk) \
+  (XLO ((op), (bo), (xop), (lk)) | (((cb) & 3) << 16))
+#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1)
+
+/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed.  */
+#define XLBB_MASK (XL_MASK | BB_MASK)
+#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
+#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
+
+/* An XL_MASK with the BO and BB fields fixed.  */
+#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
+
+/* An XL_MASK with the BO, BI and BB fields fixed.  */
+#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK)
+
+/* An XO form instruction.  */
+#define XO(op, xop, oe, rc) \
+  (OP (op) | (((xop) & 0x1ff) << 1) | (((oe) & 1) << 10) | ((rc) & 1))
+#define XO_MASK XO (0x3f, 0x1ff, 1, 1)
+
+/* An XO_MASK with the RB field fixed.  */
+#define XORB_MASK (XO_MASK | RB_MASK)
+
+/* An XS form instruction.  */
+#define XS(op, xop, rc) (OP (op) | (((xop) & 0x1ff) << 2) | ((rc) & 1))
+#define XS_MASK XS (0x3f, 0x1ff, 1)
+
+/* A mask for the FXM version of an XFX form instruction.  */
+#define XFXFXM_MASK (X_MASK | (1 << 20) | (1 << 11))
+
+/* An XFX form instruction with the FXM field filled in.  */
+#define XFXM(op, xop, fxm) \
+  (X ((op), (xop)) | (((fxm) & 0xff) << 12))
+
+/* An XFX form instruction with the SPR field filled in.  */
+#define XSPR(op, xop, spr) \
+  (X ((op), (xop)) | (((spr) & 0x1f) << 16) | (((spr) & 0x3e0) << 6))
+#define XSPR_MASK (X_MASK | SPR_MASK)
+
+/* An XFX form instruction with the SPR field filled in except for the
+   SPRBAT field.  */
+#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK)
+
+/* An XFX form instruction with the SPR field filled in except for the
+   SPRG field.  */
+#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK)
+
+/* The BO encodings used in extended conditional branch mnemonics.  */
+#define BODNZF	(0x0)
+#define BODNZFP	(0x1)
+#define BODZF	(0x2)
+#define BODZFP	(0x3)
+#define BOF	(0x4)
+#define BOFP	(0x5)
+#define BODNZT	(0x8)
+#define BODNZTP	(0x9)
+#define BODZT	(0xa)
+#define BODZTP	(0xb)
+#define BOT	(0xc)
+#define BOTP	(0xd)
+#define BODNZ	(0x10)
+#define BODNZP	(0x11)
+#define BODZ	(0x12)
+#define BODZP	(0x13)
+#define BOU	(0x14)
+
+/* The BI condition bit encodings used in extended conditional branch
+   mnemonics.  */
+#define CBLT	(0)
+#define CBGT	(1)
+#define CBEQ	(2)
+#define CBSO	(3)
+
+/* The TO encodings used in extended trap mnemonics.  */
+#define TOLGT	(0x1)
+#define TOLLT	(0x2)
+#define TOEQ	(0x4)
+#define TOLGE	(0x5)
+#define TOLNL	(0x5)
+#define TOLLE	(0x6)
+#define TOLNG	(0x6)
+#define TOGT	(0x8)
+#define TOGE	(0xc)
+#define TONL	(0xc)
+#define TOLT	(0x10)
+#define TOLE	(0x14)
+#define TONG	(0x14)
+#define TONE	(0x18)
+#define TOU	(0x1f)
+
+/* Smaller names for the flags so each entry in the opcodes table will
+   fit on a single line.  */
+#undef PPC
+#define PPC PPC_OPCODE_PPC
+#define POWER PPC_OPCODE_POWER
+#define POWER2 PPC_OPCODE_POWER2
+#define B32 PPC_OPCODE_32
+#define B64 PPC_OPCODE_64
+#define M601 PPC_OPCODE_601
+
+/* The opcode table.
+
+   The format of the opcode table is:
+
+   NAME	     OPCODE	MASK		FLAGS		{ OPERANDS }
+
+   NAME is the name of the instruction.
+   OPCODE is the instruction opcode.
+   MASK is the opcode mask; this is used to tell the disassembler
+     which bits in the actual opcode must match OPCODE.
+   FLAGS are flags indicated what processors support the instruction.
+   OPERANDS is the list of operands.
+
+   The disassembler reads the table in order and prints the first
+   instruction which matches, so this table is sorted to put more
+   specific instructions before more general instructions.  It is also
+   sorted by major opcode.  */
+
+const struct powerpc_opcode powerpc_opcodes[] = {
+{ "tdlgti",  OPTO(2,TOLGT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdllti",  OPTO(2,TOLLT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdeqi",   OPTO(2,TOEQ), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlgei",  OPTO(2,TOLGE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlnli",  OPTO(2,TOLNL), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdllei",  OPTO(2,TOLLE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlngi",  OPTO(2,TOLNG), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdgti",   OPTO(2,TOGT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdgei",   OPTO(2,TOGE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdnli",   OPTO(2,TONL), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlti",   OPTO(2,TOLT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlei",   OPTO(2,TOLE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdngi",   OPTO(2,TONG), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdnei",   OPTO(2,TONE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdi",     OP(2),	OP_MASK,	PPC|B64,	{ TO, RA, SI } },
+
+{ "twlgti",  OPTO(3,TOLGT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlgti",   OPTO(3,TOLGT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twllti",  OPTO(3,TOLLT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tllti",   OPTO(3,TOLLT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "tweqi",   OPTO(3,TOEQ), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "teqi",    OPTO(3,TOEQ), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlgei",  OPTO(3,TOLGE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlgei",   OPTO(3,TOLGE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlnli",  OPTO(3,TOLNL), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlnli",   OPTO(3,TOLNL), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twllei",  OPTO(3,TOLLE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tllei",   OPTO(3,TOLLE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlngi",  OPTO(3,TOLNG), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlngi",   OPTO(3,TOLNG), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twgti",   OPTO(3,TOGT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tgti",    OPTO(3,TOGT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twgei",   OPTO(3,TOGE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tgei",    OPTO(3,TOGE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twnli",   OPTO(3,TONL), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tnli",    OPTO(3,TONL), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlti",   OPTO(3,TOLT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlti",    OPTO(3,TOLT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlei",   OPTO(3,TOLE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlei",    OPTO(3,TOLE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twngi",   OPTO(3,TONG), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tngi",    OPTO(3,TONG), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twnei",   OPTO(3,TONE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tnei",    OPTO(3,TONE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twi",     OP(3),	OP_MASK,	PPC,		{ TO, RA, SI } },
+{ "ti",      OP(3),	OP_MASK,	POWER,		{ TO, RA, SI } },
+
+{ "mulli",   OP(7),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "muli",    OP(7),	OP_MASK,	POWER,		{ RT, RA, SI } },
+
+{ "subfic",  OP(8),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "sfi",     OP(8),	OP_MASK,	POWER,		{ RT, RA, SI } },
+
+{ "dozi",    OP(9),	OP_MASK,	POWER|M601,	{ RT, RA, SI } },
+
+{ "cmplwi",  OPL(10,0),	OPL_MASK,	PPC,		{ OBF, RA, UI } },
+{ "cmpldi",  OPL(10,1), OPL_MASK,	PPC|B64,	{ OBF, RA, UI } },
+{ "cmpli",   OP(10),	OP_MASK,	PPC,		{ BF, L, RA, UI } },
+{ "cmpli",   OP(10),	OP_MASK,	POWER,		{ BF, RA, UI } },
+
+{ "cmpwi",   OPL(11,0),	OPL_MASK,	PPC,		{ OBF, RA, SI } },
+{ "cmpdi",   OPL(11,1),	OPL_MASK,	PPC|B64,	{ OBF, RA, SI } },
+{ "cmpi",    OP(11),	OP_MASK,	PPC,		{ BF, L, RA, SI } },
+{ "cmpi",    OP(11),	OP_MASK,	POWER,		{ BF, RA, SI } },
+
+{ "addic",   OP(12),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "ai",	     OP(12),	OP_MASK,	POWER,		{ RT, RA, SI } },
+{ "subic",   OP(12),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+
+{ "addic.",  OP(13),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "ai.",     OP(13),	OP_MASK,	POWER,		{ RT, RA, SI } },
+{ "subic.",  OP(13),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+
+{ "li",	     OP(14),	DRA_MASK,	PPC,		{ RT, SI } },
+{ "lil",     OP(14),	DRA_MASK,	POWER,		{ RT, SI } },
+{ "addi",    OP(14),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "cal",     OP(14),	OP_MASK,	POWER,		{ RT, D, RA } },
+{ "subi",    OP(14),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+{ "la",	     OP(14),	OP_MASK,	PPC,		{ RT, D, RA } },
+
+{ "lis",     OP(15),	DRA_MASK,	PPC,		{ RT, SISIGNOPT } },
+{ "liu",     OP(15),	DRA_MASK,	POWER,		{ RT, SISIGNOPT } },
+{ "addis",   OP(15),	OP_MASK,	PPC,		{ RT,RA,SISIGNOPT } },
+{ "cau",     OP(15),	OP_MASK,	POWER,		{ RT,RA,SISIGNOPT } },
+{ "subis",   OP(15),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+
+{ "bdnz-",   BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdnz+",   BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdnz",    BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC,	{ BD } },
+{ "bdn",     BBO(16,BODNZ,0,0), BBOYBI_MASK, POWER,	{ BD } },
+{ "bdnzl-",  BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdnzl+",  BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdnzl",   BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC,	{ BD } },
+{ "bdnl",    BBO(16,BODNZ,0,1), BBOYBI_MASK, POWER,	{ BD } },
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 03'
echo 'File patch-2.3.4 is continued in part 04'
echo 04 > _shar_seq_.tmp
#!/bin/sh
# this is part 05 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 05; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+
+{ "sthx",    X(31,407),	X_MASK,		PPC|POWER,	{ RS, RA, RB } },
+
+{ "lfqx",    X(31,791),	X_MASK,		POWER2,		{ FRT, RA, RB } },
+
+{ "lfqux",   X(31,823),	X_MASK,		POWER2,		{ FRT, RA, RB } },
+
+{ "stfqx",   X(31,919),	X_MASK,		POWER2,		{ FRS, RA, RB } },
+
+{ "stfqux",  X(31,951),	X_MASK,		POWER2,		{ FRS, RA, RB } },
+
+{ "orc",     XRC(31,412,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "orc.",    XRC(31,412,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "sradi",   XS(31,413,0), XS_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+{ "sradi.",  XS(31,413,1), XS_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+
+{ "slbie",   X(31,434),	XRTRA_MASK,	PPC|B64,	{ RB } },
+
+{ "ecowx",   X(31,438),	X_MASK,		PPC,		{ RT, RA, RB } },
+
+{ "sthux",   X(31,439),	X_MASK,		PPC|POWER,	{ RS, RAS, RB } },
+
+{ "mr",	     XRC(31,444,0), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "or",      XRC(31,444,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "mr.",     XRC(31,444,1), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "or.",     XRC(31,444,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "mtdcr",   X(31,451),	X_MASK,		PPC,		{ SPR, RS } },
+
+{ "divdu",   XO(31,457,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divdu.",  XO(31,457,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divduo",  XO(31,457,1,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divduo.", XO(31,457,1,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "divwu",   XO(31,459,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwu.",  XO(31,459,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwuo",  XO(31,459,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwuo.", XO(31,459,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "mtmq",    XSPR(31,467,0), XSPR_MASK,	POWER|M601,	{ RS } },
+{ "mtxer",   XSPR(31,467,1), XSPR_MASK,	PPC|POWER,	{ RS } },
+{ "mtlr",    XSPR(31,467,8), XSPR_MASK,	PPC|POWER,	{ RS } },
+{ "mtctr",   XSPR(31,467,9), XSPR_MASK,	PPC|POWER,	{ RS } },
+{ "mttid",   XSPR(31,467,17), XSPR_MASK, POWER,		{ RS } },
+{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtdar",   XSPR(31,467,19), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtrtcu",  XSPR(31,467,20), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtrtcl",  XSPR(31,467,21), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtdec",   XSPR(31,467,22), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsdr0",  XSPR(31,467,24), XSPR_MASK, POWER,		{ RS } },
+{ "mtsdr1",  XSPR(31,467,25), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsrr0",  XSPR(31,467,26), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsrr1",  XSPR(31,467,27), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsprg",  XSPR(31,467,272), XSPRG_MASK, PPC,		{ SPRG, RS } },
+{ "mtasr",   XSPR(31,467,280), XSPR_MASK, PPC|B64,	{ RS } },
+{ "mtear",   XSPR(31,467,282), XSPR_MASK, PPC,		{ RS } },
+{ "mttbl",   XSPR(31,467,284), XSPR_MASK, PPC,		{ RS } },
+{ "mttbu",   XSPR(31,467,285), XSPR_MASK, PPC,		{ RS } },
+{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtspr",   X(31,467),	X_MASK,		PPC|POWER,	{ SPR, RS } },
+
+{ "dcbi",    X(31,470),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "nand",    XRC(31,476,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "nand.",   XRC(31,476,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "nabs",    XO(31,488,0,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "nabs.",   XO(31,488,0,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "nabso",   XO(31,488,1,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "nabso.",  XO(31,488,1,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+
+{ "divd",    XO(31,489,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divd.",   XO(31,489,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divdo",   XO(31,489,1,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divdo.",  XO(31,489,1,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "divw",    XO(31,491,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divw.",   XO(31,491,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwo",   XO(31,491,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwo.",  XO(31,491,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "slbia",   X(31,498),	0xffffffff,	PPC|B64,	{ 0 } },
+
+{ "cli",     X(31,502), XRB_MASK,	POWER,		{ RT, RA } },
+
+{ "mcrxr",   X(31,512),	XRARB_MASK|(3<<21), PPC|POWER,	{ BF } },
+
+{ "clcs",    X(31,531), XRB_MASK,	POWER|M601,	{ RT, RA } },
+
+{ "lswx",    X(31,533),	X_MASK,		PPC,		{ RT, RA, RB } },
+{ "lsx",     X(31,533),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "lwbrx",   X(31,534),	X_MASK,		PPC,		{ RT, RA, RB } },
+{ "lbrx",    X(31,534),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "lfsx",    X(31,535),	X_MASK,		PPC|POWER,	{ FRT, RA, RB } },
+
+{ "srw",     XRC(31,536,0), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sr",      XRC(31,536,0), X_MASK,	POWER,		{ RA, RS, RB } },
+{ "srw.",    XRC(31,536,1), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sr.",     XRC(31,536,1), X_MASK,	POWER,		{ RA, RS, RB } },
+
+{ "rrib",    XRC(31,537,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "rrib.",   XRC(31,537,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "srd",     XRC(31,539,0), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "srd.",    XRC(31,539,1), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+
+{ "maskir",  XRC(31,541,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "maskir.", XRC(31,541,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "tlbsync", X(31,566),	0xffffffff,	PPC,		{ 0 } },
+
+{ "lfsux",   X(31,567),	X_MASK,		PPC|POWER,	{ FRT, RAS, RB } },
+
+{ "mfsr",    X(31,595),	XRB_MASK|(1<<20), PPC|POWER|B32, { RT, SR } },
+
+{ "lswi",    X(31,597),	X_MASK,		PPC,		{ RT, RA, NB } },
+{ "lsi",     X(31,597),	X_MASK,		POWER,		{ RT, RA, NB } },
+
+{ "sync",    X(31,598), 0xffffffff,	PPC,		{ 0 } },
+{ "dcs",     X(31,598), 0xffffffff,	POWER,		{ 0 } },
+
+{ "lfdx",    X(31,599), X_MASK,		PPC|POWER,	{ FRT, RA, RB } },
+
+{ "mfsri",   X(31,627), X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "dclst",   X(31,630), XRB_MASK,	POWER,		{ RS, RA } },
+
+{ "lfdux",   X(31,631), X_MASK,		PPC|POWER,	{ FRT, RAS, RB } },
+
+{ "mfsrin",  X(31,659), XRA_MASK,	PPC|B32,	{ RT, RB } },
+
+{ "stswx",   X(31,661), X_MASK,		PPC,		{ RS, RA, RB } },
+{ "stsx",    X(31,661), X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "stwbrx",  X(31,662), X_MASK,		PPC,		{ RS, RA, RB } },
+{ "stbrx",   X(31,662), X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "stfsx",   X(31,663), X_MASK,		PPC|POWER,	{ FRS, RA, RB } },
+
+{ "srq",     XRC(31,664,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "srq.",    XRC(31,664,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sre",     XRC(31,665,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sre.",    XRC(31,665,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "stfsux",  X(31,695),	X_MASK,		PPC|POWER,	{ FRS, RAS, RB } },
+
+{ "sriq",    XRC(31,696,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "sriq.",   XRC(31,696,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "stswi",   X(31,725),	X_MASK,		PPC,		{ RS, RA, NB } },
+{ "stsi",    X(31,725),	X_MASK,		POWER,		{ RS, RA, NB } },
+
+{ "stfdx",   X(31,727),	X_MASK,		PPC|POWER,	{ FRS, RA, RB } },
+
+{ "srlq",    XRC(31,728,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "srlq.",   XRC(31,728,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sreq",    XRC(31,729,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sreq.",   XRC(31,729,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "stfdux",  X(31,759),	X_MASK,		PPC|POWER,	{ FRS, RAS, RB } },
+
+{ "srliq",   XRC(31,760,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "srliq.",  XRC(31,760,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "lhbrx",   X(31,790),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "sraw",    XRC(31,792,0), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sra",     XRC(31,792,0), X_MASK,	POWER,		{ RA, RS, RB } },
+{ "sraw.",   XRC(31,792,1), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sra.",    XRC(31,792,1), X_MASK,	POWER,		{ RA, RS, RB } },
+
+{ "srad",    XRC(31,794,0), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "srad.",   XRC(31,794,1), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+
+{ "rac",     X(31,818),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "srawi",   XRC(31,824,0), X_MASK,	PPC,		{ RA, RS, SH } },
+{ "srai",    XRC(31,824,0), X_MASK,	POWER,		{ RA, RS, SH } },
+{ "srawi.",  XRC(31,824,1), X_MASK,	PPC,		{ RA, RS, SH } },
+{ "srai.",   XRC(31,824,1), X_MASK,	POWER,		{ RA, RS, SH } },
+
+{ "eieio",   X(31,854),	0xffffffff,	PPC,		{ 0 } },
+
+{ "sthbrx",  X(31,918),	X_MASK,		PPC|POWER,	{ RS, RA, RB } },
+
+{ "sraq",    XRC(31,920,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sraq.",   XRC(31,920,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "srea",    XRC(31,921,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "srea.",   XRC(31,921,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "extsh",   XRC(31,922,0), XRB_MASK,	PPC,		{ RA, RS } },
+{ "exts",    XRC(31,922,0), XRB_MASK,	POWER,		{ RA, RS } },
+{ "extsh.",  XRC(31,922,1), XRB_MASK,	PPC,		{ RA, RS } },
+{ "exts.",   XRC(31,922,1), XRB_MASK,	POWER,		{ RA, RS } },
+
+{ "sraiq",   XRC(31,952,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "sraiq.",  XRC(31,952,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "extsb",   XRC(31,954,0), XRB_MASK,	PPC,		{ RA, RS} },
+{ "extsb.",  XRC(31,954,1), XRB_MASK,	PPC,		{ RA, RS} },
+
+{ "iccci",   X(31,966),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "icbi",    X(31,982),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "stfiwx",  X(31,983),	X_MASK,		PPC,		{ FRS, RA, RB } },
+
+{ "extsw",   XRC(31,986,0), XRB_MASK,	PPC,		{ RA, RS } },
+{ "extsw.",  XRC(31,986,1), XRB_MASK,	PPC,		{ RA, RS } },
+
+{ "dcbz",    X(31,1014), XRT_MASK,	PPC,		{ RA, RB } },
+{ "dclz",    X(31,1014), XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lwz",     OP(32),	OP_MASK,	PPC,		{ RT, D, RA } },
+{ "l",	     OP(32),	OP_MASK,	POWER,		{ RT, D, RA } },
+
+{ "lwzu",    OP(33),	OP_MASK,	PPC,		{ RT, D, RAL } },
+{ "lu",      OP(33),	OP_MASK,	POWER,		{ RT, D, RA } },
+
+{ "lbz",     OP(34),	OP_MASK,	PPC|POWER,	{ RT, D, RA } },
+
+{ "lbzu",    OP(35),	OP_MASK,	PPC|POWER,	{ RT, D, RAL } },
+
+{ "stw",     OP(36),	OP_MASK,	PPC,		{ RS, D, RA } },
+{ "st",      OP(36),	OP_MASK,	POWER,		{ RS, D, RA } },
+
+{ "stwu",    OP(37),	OP_MASK,	PPC,		{ RS, D, RAS } },
+{ "stu",     OP(37),	OP_MASK,	POWER,		{ RS, D, RA } },
+
+{ "stb",     OP(38),	OP_MASK,	PPC|POWER,	{ RS, D, RA } },
+
+{ "stbu",    OP(39),	OP_MASK,	PPC|POWER,	{ RS, D, RAS } },
+
+{ "lhz",     OP(40),	OP_MASK,	PPC|POWER,	{ RT, D, RA } },
+
+{ "lhzu",    OP(41),	OP_MASK,	PPC|POWER,	{ RT, D, RAL } },
+
+{ "lha",     OP(42),	OP_MASK,	PPC|POWER,	{ RT, D, RA } },
+
+{ "lhau",    OP(43),	OP_MASK,	PPC|POWER,	{ RT, D, RAL } },
+
+{ "sth",     OP(44),	OP_MASK,	PPC|POWER,	{ RS, D, RA } },
+
+{ "sthu",    OP(45),	OP_MASK,	PPC|POWER,	{ RS, D, RAS } },
+
+{ "lmw",     OP(46),	OP_MASK,	PPC,		{ RT, D, RAM } },
+{ "lm",      OP(46),	OP_MASK,	POWER,		{ RT, D, RA } },
+
+{ "stmw",    OP(47),	OP_MASK,	PPC,		{ RS, D, RA } },
+{ "stm",     OP(47),	OP_MASK,	POWER,		{ RS, D, RA } },
+
+{ "lfs",     OP(48),	OP_MASK,	PPC|POWER,	{ FRT, D, RA } },
+
+{ "lfsu",    OP(49),	OP_MASK,	PPC|POWER,	{ FRT, D, RAS } },
+
+{ "lfd",     OP(50),	OP_MASK,	PPC|POWER,	{ FRT, D, RA } },
+
+{ "lfdu",    OP(51),	OP_MASK,	PPC|POWER,	{ FRT, D, RAS } },
+
+{ "stfs",    OP(52),	OP_MASK,	PPC|POWER,	{ FRS, D, RA } },
+
+{ "stfsu",   OP(53),	OP_MASK,	PPC|POWER,	{ FRS, D, RAS } },
+
+{ "stfd",    OP(54),	OP_MASK,	PPC|POWER,	{ FRS, D, RA } },
+
+{ "stfdu",   OP(55),	OP_MASK,	PPC|POWER,	{ FRS, D, RAS } },
+
+{ "lfq",     OP(56),	OP_MASK,	POWER2,		{ FRT, D, RA } },
+
+{ "lfqu",    OP(57),	OP_MASK,	POWER2,		{ FRT, D, RA } },
+
+{ "ld",      DSO(58,0),	DS_MASK,	PPC|B64,	{ RT, DS, RA } },
+
+{ "ldu",     DSO(58,1), DS_MASK,	PPC|B64,	{ RT, DS, RAL } },
+
+{ "lwa",     DSO(58,2), DS_MASK,	PPC|B64,	{ RT, DS, RA } },
+
+{ "fdivs",   A(59,18,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fdivs.",  A(59,18,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+
+{ "fsubs",   A(59,20,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fsubs.",  A(59,20,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+
+{ "fadds",   A(59,21,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fadds.",  A(59,21,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+
+{ "fsqrts",  A(59,22,0), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+{ "fsqrts.", A(59,22,1), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+
+{ "fres",    A(59,24,0), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+{ "fres.",   A(59,24,1), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+
+{ "fmuls",   A(59,25,0), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+{ "fmuls.",  A(59,25,1), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+
+{ "fmsubs",  A(59,28,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fmsubs.", A(59,28,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fmadds",  A(59,29,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fmadds.", A(59,29,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmsubs", A(59,30,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnmsubs.",A(59,30,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmadds", A(59,31,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnmadds.",A(59,31,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "stfq",    OP(60),	OP_MASK,	POWER2,		{ FRS, D, RA } },
+
+{ "stfqu",   OP(61),	OP_MASK,	POWER2,		{ FRS, D, RA } },
+
+{ "std",     DSO(62,0),	DS_MASK,	PPC|B64,	{ RS, DS, RA } },
+
+{ "stdu",    DSO(62,1),	DS_MASK,	PPC|B64,	{ RS, DS, RAS } },
+
+{ "fcmpu",   X(63,0),	X_MASK|(3<<21),	PPC|POWER,	{ BF, FRA, FRB } },
+
+{ "frsp",    XRC(63,12,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "frsp.",   XRC(63,12,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "fctiw",   XRC(63,14,0), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcir",    XRC(63,14,0), XRA_MASK,	POWER2,		{ FRT, FRB } },
+{ "fctiw.",  XRC(63,14,1), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcir.",   XRC(63,14,1), XRA_MASK,	POWER2,		{ FRT, FRB } },
+
+{ "fctiwz",  XRC(63,15,0), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcirz",   XRC(63,15,0), XRA_MASK,	POWER2,		{ FRT, FRB } },
+{ "fctiwz.", XRC(63,15,1), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcirz.",  XRC(63,15,1), XRA_MASK,	POWER2,		{ FRT, FRB } },
+
+{ "fdiv",    A(63,18,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fd",      A(63,18,0), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+{ "fdiv.",   A(63,18,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fd.",     A(63,18,1), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+
+{ "fsub",    A(63,20,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fs",      A(63,20,0), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+{ "fsub.",   A(63,20,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fs.",     A(63,20,1), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+
+{ "fadd",    A(63,21,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fa",      A(63,21,0), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+{ "fadd.",   A(63,21,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fa.",     A(63,21,1), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+
+{ "fsqrt",   A(63,22,0), AFRAFRC_MASK,	PPC|POWER2,	{ FRT, FRB } },
+{ "fsqrt.",  A(63,22,1), AFRAFRC_MASK,	PPC|POWER2,	{ FRT, FRB } },
+
+{ "fsel",    A(63,23,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fsel.",   A(63,23,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fmul",    A(63,25,0), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+{ "fm",      A(63,25,0), AFRB_MASK,	POWER,		{ FRT, FRA, FRC } },
+{ "fmul.",   A(63,25,1), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+{ "fm.",     A(63,25,1), AFRB_MASK,	POWER,		{ FRT, FRA, FRC } },
+
+{ "frsqrte", A(63,26,0), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+{ "frsqrte.",A(63,26,1), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+
+{ "fmsub",   A(63,28,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fms",     A(63,28,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fmsub.",  A(63,28,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fms.",    A(63,28,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fmadd",   A(63,29,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fma",     A(63,29,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fmadd.",  A(63,29,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fma.",    A(63,29,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmsub",  A(63,30,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnms",    A(63,30,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fnmsub.", A(63,30,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnms.",   A(63,30,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmadd",  A(63,31,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnma",    A(63,31,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fnmadd.", A(63,31,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnma.",   A(63,31,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fcmpo",   X(63,30),	X_MASK|(3<<21),	PPC|POWER,	{ BF, FRA, FRB } },
+
+{ "mtfsb1",  XRC(63,38,0), XRARB_MASK,	PPC|POWER,	{ BT } },
+{ "mtfsb1.", XRC(63,38,1), XRARB_MASK,	PPC|POWER,	{ BT } },
+
+{ "fneg",    XRC(63,40,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fneg.",   XRC(63,40,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "mcrfs",   X(63,64),	XRB_MASK|(3<<21)|(3<<16), PPC|POWER, { BF, BFA } },
+
+{ "mtfsb0",  XRC(63,70,0), XRARB_MASK,	PPC|POWER,	{ BT } },
+{ "mtfsb0.", XRC(63,70,1), XRARB_MASK,	PPC|POWER,	{ BT } },
+
+{ "fmr",     XRC(63,72,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fmr.",    XRC(63,72,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "mtfsfi",  XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), PPC|POWER, { BF, U } },
+{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), PPC|POWER, { BF, U } },
+
+{ "fnabs",   XRC(63,136,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fnabs.",  XRC(63,136,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "fabs",    XRC(63,264,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fabs.",   XRC(63,264,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "mffs",    XRC(63,583,0), XRARB_MASK,	PPC|POWER,	{ FRT } },
+{ "mffs.",   XRC(63,583,1), XRARB_MASK,	PPC|POWER,	{ FRT } },
+
+{ "mtfsf",   XFL(63,711,0), XFL_MASK,	PPC|POWER,	{ FLM, FRB } },
+{ "mtfsf.",  XFL(63,711,1), XFL_MASK,	PPC|POWER,	{ FLM, FRB } },
+
+{ "fctid",   XRC(63,814,0), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+{ "fctid.",  XRC(63,814,1), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+
+{ "fctidz",  XRC(63,815,0), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+{ "fctidz.", XRC(63,815,1), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+
+{ "fcfid",   XRC(63,846,0), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+{ "fcfid.",  XRC(63,846,1), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+
+};
+
+const int powerpc_num_opcodes =
+  sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]);
+
+/* The macro table.  This is only used by the assembler.  */
+
+const struct powerpc_macro powerpc_macros[] = {
+{ "extldi",  4,   PPC|B64,	"rldicr %0,%1,%3,(%2)-1" },
+{ "extldi.", 4,   PPC|B64,	"rldicr. %0,%1,%3,(%2)-1" },
+{ "extrdi",  4,   PPC|B64,	"rldicl %0,%1,(%2)+(%3),64-(%2)" },
+{ "extrdi.", 4,   PPC|B64,	"rldicl. %0,%1,(%2)+(%3),64-(%2)" },
+{ "insrdi",  4,   PPC|B64,	"rldimi %0,%1,64-((%2)+(%3)),%3" },
+{ "insrdi.", 4,   PPC|B64,	"rldimi. %0,%1,64-((%2)+(%3)),%3" },
+{ "rotrdi",  3,   PPC|B64,	"rldicl %0,%1,64-(%2),0" },
+{ "rotrdi.", 3,   PPC|B64,	"rldicl. %0,%1,64-(%2),0" },
+{ "sldi",    3,   PPC|B64,	"rldicr %0,%1,%2,63-(%2)" },
+{ "sldi.",   3,   PPC|B64,	"rldicr. %0,%1,%2,63-(%2)" },
+{ "srdi",    3,   PPC|B64,	"rldicl %0,%1,64-(%2),%2" },
+{ "srdi.",   3,   PPC|B64,	"rldicl. %0,%1,64-(%2),%2" },
+{ "clrrdi",  3,   PPC|B64,	"rldicr %0,%1,0,63-(%2)" },
+{ "clrrdi.", 3,   PPC|B64,	"rldicr. %0,%1,0,63-(%2)" },
+{ "clrlsldi",4,   PPC|B64,	"rldic %0,%1,%3,(%2)-(%3)" },
+{ "clrlsldi.",4,  PPC|B64,	"rldic. %0,%1,%3,(%2)-(%3)" },
+
+{ "extlwi",  4,   PPC,		"rlwinm %0,%1,%3,0,(%2)-1" },
+{ "extlwi.", 4,   PPC,		"rlwinm. %0,%1,%3,0,(%2)-1" },
+{ "extrwi",  4,   PPC,		"rlwinm %0,%1,(%2)+(%3),32-(%2),31" },
+{ "extrwi.", 4,   PPC,		"rlwinm. %0,%1,(%2)+(%3),32-(%2),31" },
+{ "inslwi",  4,   PPC,		"rlwimi %0,%1,32-(%3),%3,(%2)+(%3)-1" },
+{ "inslwi.", 4,   PPC,		"rlwimi. %0,%1,32-(%3),%3,(%2)+(%3)-1" },
+{ "insrwi",  4,   PPC,		"rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" },
+{ "insrwi.", 4,   PPC,		"rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"},
+{ "rotrwi",  3,   PPC,		"rlwinm %0,%1,32-(%2),0,31" },
+{ "rotrwi.", 3,   PPC,		"rlwinm. %0,%1,32-(%2),0,31" },
+{ "slwi",    3,   PPC,		"rlwinm %0,%1,%2,0,31-(%2)" },
+{ "sli",     3,   POWER,	"rlinm %0,%1,%2,0,31-(%2)" },
+{ "slwi.",   3,   PPC,		"rlwinm. %0,%1,%2,0,31-(%2)" },
+{ "sli.",    3,   POWER,	"rlinm. %0,%1,%2,0,31-(%2)" },
+{ "srwi",    3,   PPC,		"rlwinm %0,%1,32-(%2),%2,31" },
+{ "sri",     3,   POWER,	"rlinm %0,%1,32-(%2),%2,31" },
+{ "srwi.",   3,   PPC,		"rlwinm. %0,%1,32-(%2),%2,31" },
+{ "sri.",    3,   POWER,	"rlinm. %0,%1,32-(%2),%2,31" },
+{ "clrrwi",  3,   PPC,		"rlwinm %0,%1,0,0,31-(%2)" },
+{ "clrrwi.", 3,   PPC,		"rlwinm. %0,%1,0,0,31-(%2)" },
+{ "clrlslwi",4,   PPC,		"rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" },
+{ "clrlslwi.",4,  PPC,		"rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" },
+
+};
+
+const int powerpc_num_macros =
+  sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/ppc.h linux/arch/ppc/xmon/ppc.h
--- v2.3.3/linux/arch/ppc/xmon/ppc.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/ppc.h	Sat May 22 13:03:00 1999
@@ -0,0 +1,240 @@
+/* ppc.h -- Header file for PowerPC opcode table
+   Copyright 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef PPC_H
+#define PPC_H
+
+/* The opcode table is an array of struct powerpc_opcode.  */
+
+struct powerpc_opcode
+{
+  /* The opcode name.  */
+  const char *name;
+
+  /* The opcode itself.  Those bits which will be filled in with
+     operands are zeroes.  */
+  unsigned long opcode;
+
+  /* The opcode mask.  This is used by the disassembler.  This is a
+     mask containing ones indicating those bits which must match the
+     opcode field, and zeroes indicating those bits which need not
+     match (and are presumably filled in by operands).  */
+  unsigned long mask;
+
+  /* One bit flags for the opcode.  These are used to indicate which
+     specific processors support the instructions.  The defined values
+     are listed below.  */
+  unsigned long flags;
+
+  /* An array of operand codes.  Each code is an index into the
+     operand table.  They appear in the order which the operands must
+     appear in assembly code, and are terminated by a zero.  */
+  unsigned char operands[8];
+};
+
+/* The table itself is sorted by major opcode number, and is otherwise
+   in the order in which the disassembler should consider
+   instructions.  */
+extern const struct powerpc_opcode powerpc_opcodes[];
+extern const int powerpc_num_opcodes;
+
+/* Values defined for the flags field of a struct powerpc_opcode.  */
+
+/* Opcode is defined for the PowerPC architecture.  */
+#define PPC_OPCODE_PPC (01)
+
+/* Opcode is defined for the POWER (RS/6000) architecture.  */
+#define PPC_OPCODE_POWER (02)
+
+/* Opcode is defined for the POWER2 (Rios 2) architecture.  */
+#define PPC_OPCODE_POWER2 (04)
+
+/* Opcode is only defined on 32 bit architectures.  */
+#define PPC_OPCODE_32 (010)
+
+/* Opcode is only defined on 64 bit architectures.  */
+#define PPC_OPCODE_64 (020)
+
+/* Opcode is supported by the Motorola PowerPC 601 processor.  The 601
+   is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
+   but it also supports many additional POWER instructions.  */
+#define PPC_OPCODE_601 (040)
+
+/* A macro to extract the major opcode from an instruction.  */
+#define PPC_OP(i) (((i) >> 26) & 0x3f)
+
+/* The operands table is an array of struct powerpc_operand.  */
+
+struct powerpc_operand
+{
+  /* The number of bits in the operand.  */
+  int bits;
+
+  /* How far the operand is left shifted in the instruction.  */
+  int shift;
+
+  /* Insertion function.  This is used by the assembler.  To insert an
+     operand value into an instruction, check this field.
+
+     If it is NULL, execute
+         i |= (op & ((1 << o->bits) - 1)) << o->shift;
+     (i is the instruction which we are filling in, o is a pointer to
+     this structure, and op is the opcode value; this assumes twos
+     complement arithmetic).
+
+     If this field is not NULL, then simply call it with the
+     instruction and the operand value.  It will return the new value
+     of the instruction.  If the ERRMSG argument is not NULL, then if
+     the operand value is illegal, *ERRMSG will be set to a warning
+     string (the operand will be inserted in any case).  If the
+     operand value is legal, *ERRMSG will be unchanged (most operands
+     can accept any value).  */
+  unsigned long (*insert) PARAMS ((unsigned long instruction, long op,
+				   const char **errmsg));
+
+  /* Extraction function.  This is used by the disassembler.  To
+     extract this operand type from an instruction, check this field.
+
+     If it is NULL, compute
+         op = ((i) >> o->shift) & ((1 << o->bits) - 1);
+	 if ((o->flags & PPC_OPERAND_SIGNED) != 0
+	     && (op & (1 << (o->bits - 1))) != 0)
+	   op -= 1 << o->bits;
+     (i is the instruction, o is a pointer to this structure, and op
+     is the result; this assumes twos complement arithmetic).
+
+     If this field is not NULL, then simply call it with the
+     instruction value.  It will return the value of the operand.  If
+     the INVALID argument is not NULL, *INVALID will be set to
+     non-zero if this operand type can not actually be extracted from
+     this operand (i.e., the instruction does not match).  If the
+     operand is valid, *INVALID will not be changed.  */
+  long (*extract) PARAMS ((unsigned long instruction, int *invalid));
+
+  /* One bit syntax flags.  */
+  unsigned long flags;
+};
+
+/* Elements in the table are retrieved by indexing with values from
+   the operands field of the powerpc_opcodes table.  */
+
+extern const struct powerpc_operand powerpc_operands[];
+
+/* Values defined for the flags field of a struct powerpc_operand.  */
+
+/* This operand takes signed values.  */
+#define PPC_OPERAND_SIGNED (01)
+
+/* This operand takes signed values, but also accepts a full positive
+   range of values when running in 32 bit mode.  That is, if bits is
+   16, it takes any value from -0x8000 to 0xffff.  In 64 bit mode,
+   this flag is ignored.  */
+#define PPC_OPERAND_SIGNOPT (02)
+
+/* This operand does not actually exist in the assembler input.  This
+   is used to support extended mnemonics such as mr, for which two
+   operands fields are identical.  The assembler should call the
+   insert function with any op value.  The disassembler should call
+   the extract function, ignore the return value, and check the value
+   placed in the valid argument.  */
+#define PPC_OPERAND_FAKE (04)
+
+/* The next operand should be wrapped in parentheses rather than
+   separated from this one by a comma.  This is used for the load and
+   store instructions which want their operands to look like
+       reg,displacement(reg)
+   */
+#define PPC_OPERAND_PARENS (010)
+
+/* This operand may use the symbolic names for the CR fields, which
+   are
+       lt  0	gt  1	eq  2	so  3	un  3
+       cr0 0	cr1 1	cr2 2	cr3 3
+       cr4 4	cr5 5	cr6 6	cr7 7
+   These may be combined arithmetically, as in cr2*4+gt.  These are
+   only supported on the PowerPC, not the POWER.  */
+#define PPC_OPERAND_CR (020)
+
+/* This operand names a register.  The disassembler uses this to print
+   register names with a leading 'r'.  */
+#define PPC_OPERAND_GPR (040)
+
+/* This operand names a floating point register.  The disassembler
+   prints these with a leading 'f'.  */
+#define PPC_OPERAND_FPR (0100)
+
+/* This operand is a relative branch displacement.  The disassembler
+   prints these symbolically if possible.  */
+#define PPC_OPERAND_RELATIVE (0200)
+
+/* This operand is an absolute branch address.  The disassembler
+   prints these symbolically if possible.  */
+#define PPC_OPERAND_ABSOLUTE (0400)
+
+/* This operand is optional, and is zero if omitted.  This is used for
+   the optional BF and L fields in the comparison instructions.  The
+   assembler must count the number of operands remaining on the line,
+   and the number of operands remaining for the opcode, and decide
+   whether this operand is present or not.  The disassembler should
+   print this operand out only if it is not zero.  */
+#define PPC_OPERAND_OPTIONAL (01000)
+
+/* This flag is only used with PPC_OPERAND_OPTIONAL.  If this operand
+   is omitted, then for the next operand use this operand value plus
+   1, ignoring the next operand field for the opcode.  This wretched
+   hack is needed because the Power rotate instructions can take
+   either 4 or 5 operands.  The disassembler should print this operand
+   out regardless of the PPC_OPERAND_OPTIONAL field.  */
+#define PPC_OPERAND_NEXT (02000)
+
+/* This operand should be regarded as a negative number for the
+   purposes of overflow checking (i.e., the normal most negative
+   number is disallowed and one more than the normal most positive
+   number is allowed).  This flag will only be set for a signed
+   operand.  */
+#define PPC_OPERAND_NEGATIVE (04000)
+
+/* The POWER and PowerPC assemblers use a few macros.  We keep them
+   with the operands table for simplicity.  The macro table is an
+   array of struct powerpc_macro.  */
+
+struct powerpc_macro
+{
+  /* The macro name.  */
+  const char *name;
+
+  /* The number of operands the macro takes.  */
+  unsigned int operands;
+
+  /* One bit flags for the opcode.  These are used to indicate which
+     specific processors support the instructions.  The values are the
+     same as those for the struct powerpc_opcode flags field.  */
+  unsigned long flags;
+
+  /* A format string to turn the macro into a normal instruction.
+     Each %N in the string is replaced with operand number N (zero
+     based).  */
+  const char *format;
+};
+
+extern const struct powerpc_macro powerpc_macros[];
+extern const int powerpc_num_macros;
+
+#endif /* PPC_H */
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/privinst.h linux/arch/ppc/xmon/privinst.h
--- v2.3.3/linux/arch/ppc/xmon/privinst.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/privinst.h	Sat May 22 13:03:00 1999
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+#define GETREG(reg)		\
+    static inline int get_ ## reg (void)	\
+	{ int ret; asm volatile ("mf" #reg " %0" : "=r" (ret) :); return ret; }
+
+#define SETREG(reg)		\
+    static inline void set_ ## reg (int val)	\
+	{ asm volatile ("mt" #reg " %0" : : "r" (val)); }
+
+GETREG(msr)
+SETREG(msr)
+GETREG(cr)
+
+#define GSETSPR(n, name)	\
+    static inline int get_ ## name (void) \
+	{ int ret; asm volatile ("mfspr %0," #n : "=r" (ret) : ); return ret; } \
+    static inline void set_ ## name (int val) \
+	{ asm volatile ("mtspr " #n ",%0" : : "r" (val)); }
+
+GSETSPR(0, mq)
+GSETSPR(1, xer)
+GSETSPR(4, rtcu)
+GSETSPR(5, rtcl)
+GSETSPR(8, lr)
+GSETSPR(9, ctr)
+GSETSPR(18, dsisr)
+GSETSPR(19, dar)
+GSETSPR(22, dec)
+GSETSPR(25, sdr1)
+GSETSPR(26, srr0)
+GSETSPR(27, srr1)
+GSETSPR(272, sprg0)
+GSETSPR(273, sprg1)
+GSETSPR(274, sprg2)
+GSETSPR(275, sprg3)
+GSETSPR(282, ear)
+GSETSPR(287, pvr)
+GSETSPR(528, bat0u)
+GSETSPR(529, bat0l)
+GSETSPR(530, bat1u)
+GSETSPR(531, bat1l)
+GSETSPR(532, bat2u)
+GSETSPR(533, bat2l)
+GSETSPR(534, bat3u)
+GSETSPR(535, bat3l)
+GSETSPR(1008, hid0)
+GSETSPR(1009, hid1)
+GSETSPR(1010, iabr)
+GSETSPR(1013, dabr)
+GSETSPR(1023, pir)
+
+static inline int get_sr(int n)
+{
+    int ret;
+
+    asm (" mfsrin %0,%1" : "=r" (ret) : "r" (n << 28));
+    return ret;
+}
+
+static inline void set_sr(int n, int val)
+{
+    asm ("mtsrin %0,%1" : : "r" (val), "r" (n << 28));
+}
+
+static inline void store_inst(void *p)
+{
+    asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
+}
+
+
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/setjmp.c linux/arch/ppc/xmon/setjmp.c
--- v2.3.3/linux/arch/ppc/xmon/setjmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/setjmp.c	Sat May 22 13:03:00 1999
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * NB this file must be compiled with -O2.
+ */
+
+int
+xmon_setjmp(long *buf)
+{
+    asm ("mflr 0; stw 0,0(%0);"
+	 "stw 1,4(%0); stw 2,8(%0);"
+	 "mfcr 0; stw 0,12(%0);"
+	 "stmw 13,16(%0)"
+	 : : "r" (buf));
+    /* XXX should save fp regs as well */
+    return 0;
+}
+
+void
+xmon_longjmp(long *buf, int val)
+{
+    if (val == 0)
+	val = 1;
+    asm ("lmw 13,16(%0);"
+	 "lwz 0,12(%0); mtcrf 0x38,0;"
+	 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+	 "mtlr 0; mr 3,%1"
+	 : : "r" (buf), "r" (val));
+}
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
--- v2.3.3/linux/arch/ppc/xmon/start.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/start.c	Wed May 26 16:55:40 1999
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/string.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/adb.h>
+#include <asm/prom.h>
+
+static volatile unsigned char *sccc, *sccd;
+unsigned long TXRDY, RXRDY;
+extern void xmon_printf(const char *fmt, ...);
+
+static int console = 0;
+
+void buf_access(void)
+{
+	if ( _machine == _MACH_chrp )
+		sccd[3] &= ~0x80;	/* reset DLAB */
+}
+
+void
+xmon_map_scc(void)
+{
+	volatile unsigned char *base;
+
+	if ( _machine == _MACH_Pmac )
+	{
+		struct device_node *np;
+#ifdef CHRP_ESCC
+		unsigned long addr = 0xc1013020;
+#else
+		unsigned long addr = 0xf3013030;
+#endif
+		TXRDY = 4;
+		RXRDY = 1;
+		
+		np = find_devices("mac-io");
+		if (np && np->n_addrs) {
+			addr = np->addrs[0].address + 0x13000;
+			/* use the B channel on the iMac, A channel on others */
+			if (addr >= 0xf0000000)
+				addr += 0x20; /* use A channel */
+		}
+		base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
+		sccc = base + (addr & ~PAGE_MASK);
+#ifdef CHRP_ESCC
+		sccd = sccc + (0xc1013030 - 0xc1013020);
+#else
+		sccd = sccc + (0xf3013030 - 0xf3013020);
+#endif
+	}
+	else
+	{
+		/* should already be mapped by the kernel boot */
+		sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
+		sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
+		TXRDY = 0x20;
+		RXRDY = 1;
+	}
+}
+
+static int scc_initialized = 0;
+
+void xmon_init_scc(void);
+extern void pmu_poll(void);
+
+int
+xmon_write(void *handle, void *ptr, int nb)
+{
+    char *p = ptr;
+    int i, ct;
+
+    if (!scc_initialized)
+	xmon_init_scc();
+    for (i = 0; i < nb; ++i) {
+	while ((*sccc & TXRDY) == 0)
+	    if (adb_hardware == ADB_VIAPMU)
+		pmu_poll();
+	buf_access();
+	if ( console && (*p != '\r'))
+		printk("%c", *p);
+	ct = 0;
+	if ( *p == '\n')
+		ct = 1;
+	*sccd = *p++;
+	if ( ct )
+		xmon_write(handle, "\r", 1);
+    }
+    return i;
+}
+
+int
+xmon_read(void *handle, void *ptr, int nb)
+{
+    char *p = ptr;
+    int i;
+
+    if (!scc_initialized)
+	xmon_init_scc();
+    for (i = 0; i < nb; ++i) {
+	while ((*sccc & RXRDY) == 0)
+	    if (adb_hardware == ADB_VIAPMU)
+		pmu_poll();
+	buf_access();
+#if 0	
+	if ( 0/*console*/ )
+		*p++ = ppc_md.kbd_getkeycode();
+	else
+#endif		
+		*p++ = *sccd;
+    }
+    return i;
+}
+
+static unsigned char scc_inittab[] = {
+    13, 0,		/* set baud rate divisor */
+    12, 1,
+    14, 1,		/* baud rate gen enable, src=rtxc */
+    11, 0x50,		/* clocks = br gen */
+    5,  0x6a,		/* tx 8 bits, assert RTS */
+    4,  0x44,		/* x16 clock, 1 stop */
+    3,  0xc1,		/* rx enable, 8 bits */
+};
+
+void
+xmon_init_scc()
+{
+	if ( _machine == _MACH_chrp )
+	{
+		sccd[3] = 0x83; eieio();	/* LCR = 8N1 + DLAB */
+		sccd[0] = 3; eieio();		/* DLL = 38400 baud */
+		sccd[1] = 0; eieio();
+		sccd[2] = 0; eieio();		/* FCR = 0 */
+		sccd[3] = 3; eieio();		/* LCR = 8N1 */
+		sccd[1] = 0; eieio();		/* IER = 0 */
+	}
+	else
+	{
+		int i, x;
+
+		for (i = 20000; i != 0; --i) {
+			x = *sccc; eieio();
+		}
+		*sccc = 9; eieio();		/* reset A or B side */
+		*sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
+		for (i = 0; i < sizeof(scc_inittab); ++i) {
+			*sccc = scc_inittab[i];
+			eieio();
+		}
+	}
+	scc_initialized = 1;
+}
+
+#if 0
+extern int (*prom_entry)(void *);
+
+int
+xmon_exit(void)
+{
+    struct prom_args {
+	char *service;
+    } args;
+
+    for (;;) {
+	args.service = "exit";
+	(*prom_entry)(&args);
+    }
+}
+#endif
+
+void *xmon_stdin;
+void *xmon_stdout;
+void *xmon_stderr;
+
+void
+xmon_init(void)
+{
+}
+
+int
+xmon_putc(int c, void *f)
+{
+    char ch = c;
+
+    if (c == '\n')
+	xmon_putc('\r', f);
+    return xmon_write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+xmon_putchar(int c)
+{
+    return xmon_putc(c, xmon_stdout);
+}
+
+int
+xmon_fputs(char *str, void *f)
+{
+    int n = strlen(str);
+
+    return xmon_write(f, str, n) == n? 0: -1;
+}
+
+int
+xmon_readchar(void)
+{
+    char ch;
+
+    for (;;) {
+	switch (xmon_read(xmon_stdin, &ch, 1)) {
+	case 1:
+	    return ch;
+	case -1:
+	    xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+	    return -1;
+	}
+    }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+xmon_getchar(void)
+{
+    int c;
+
+    if (lineleft == 0) {
+	lineptr = line;
+	for (;;) {
+	    c = xmon_readchar();
+	    if (c == -1 || c == 4)
+		break;
+	    if (c == '\r' || c == '\n') {
+		*lineptr++ = '\n';
+		xmon_putchar('\n');
+		break;
+	    }
+	    switch (c) {
+	    case 0177:
+	    case '\b':
+		if (lineptr > line) {
+		    xmon_putchar('\b');
+		    xmon_putchar(' ');
+		    xmon_putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    case 'U' & 0x1F:
+		while (lineptr > line) {
+		    xmon_putchar('\b');
+		    xmon_putchar(' ');
+		    xmon_putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    default:
+		if (lineptr >= &line[sizeof(line) - 1])
+		    xmon_putchar('\a');
+		else {
+		    xmon_putchar(c);
+		    *lineptr++ = c;
+		}
+	    }
+	}
+	lineleft = lineptr - line;
+	lineptr = line;
+    }
+    if (lineleft == 0)
+	return -1;
+    --lineleft;
+    return *lineptr++;
+}
+
+char *
+xmon_fgets(char *str, int nb, void *f)
+{
+    char *p;
+    int c;
+
+    for (p = str; p < str + nb - 1; ) {
+	c = xmon_getchar();
+	if (c == -1) {
+	    if (p == str)
+		return 0;
+	    break;
+	}
+	*p++ = c;
+	if (c == '\n')
+	    break;
+    }
+    *p = 0;
+    return str;
+}
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/subr_prf.c linux/arch/ppc/xmon/subr_prf.c
--- v2.3.3/linux/arch/ppc/xmon/subr_prf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/subr_prf.c	Sat May 22 13:03:00 1999
@@ -0,0 +1,47 @@
+/*
+ * Written by Cort Dougan to replace the version written by
+ * Paul Mackerras that had copyright conflicts with Linux.
+ *
+ * This file makes liberal use of the standard linux utility
+ * routines to reduce the size of the binary.  We assume we can
+ * trust some parts of Linux inside the debugger.
+ *   -- Cort (co...@cs.nmt.edu)
+ *
+ * Copyright (C) 1999 Cort Dougan.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include "nonstdio.h"
+
+extern int xmon_write(void *, void *, int);
+
+void
+xmon_vfprintf(void *f, const char *fmt, va_list ap)
+{
+	char buf[2048];
+	vsprintf( buf, fmt, ap );
+	xmon_write( f, buf, strlen(buf) );
+}
+
+void
+xmon_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	xmon_vfprintf(stdout, fmt, ap);
+	va_end(ap);
+}
+
+void
+xmon_fprintf(void *f, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	xmon_vfprintf(f, fmt, ap);
+	va_end(ap);
+}
+
diff -u --recursive --new-file v2.3.3/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.3.3/linux/arch/ppc/xmon/xmon.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/xmon/xmon.c	Sat May 22 13:03:00 1999
@@ -0,0 +1,1323 @@
+/*
+ * Routines providing a simple monitor for use on the PowerMac.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex	xmon_scanhex
+#define skipbl	xmon_skipbl
+
+static unsigned adrs;
+static int size = 1;
+static unsigned ndump = 64;
+static unsigned nidump = 16;
+static int termch;
+
+static u_int bus_error_jmp[100];
+#define setjmp xmon_setjmp
+#define longjmp xmon_longjmp
+
+/* Breakpoint stuff */
+struct bpt {
+	unsigned address;
+	unsigned instr;
+	unsigned count;
+	unsigned char enabled;
+};
+
+#define NBPTS	16
+static struct bpt bpts[NBPTS];
+static struct bpt dabr;
+static struct bpt iabr;
+static unsigned bpinstr = 0x7fe00008;	/* trap */
+
+/* Prototypes */
+extern void (*debugger_fault_handler)(struct pt_regs *);
+static int cmds(struct pt_regs *);
+static int mread(unsigned, void *, int);
+static int mwrite(unsigned, void *, int);
+static void handle_fault(struct pt_regs *);
+static void byterev(unsigned char *, int);
+static void memex(void);
+static int bsesc(void);
+static void dump(void);
+static void prdump(unsigned, int);
+#ifdef __MWERKS__
+static void prndump(unsigned, int);
+static int nvreadb(unsigned);
+#endif
+static int ppc_inst_dump(unsigned, int);
+void print_address(unsigned);
+static int getsp(void);
+static void dump_hash_table(void);
+static void backtrace(struct pt_regs *);
+static void excprint(struct pt_regs *);
+static void prregs(struct pt_regs *);
+static void memops(int);
+static void memlocate(void);
+static void memzcan(void);
+static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
+int skipbl(void);
+int scanhex(unsigned *valp);
+static void scannl(void);
+static int hexdigit(int);
+void getstring(char *, int);
+static void flush_input(void);
+static int inchar(void);
+static void take_input(char *);
+/* static void openforth(void); */
+static unsigned read_spr(int);
+static void write_spr(int, unsigned);
+static void super_regs(void);
+static void remove_bpts(void);
+static void insert_bpts(void);
+static struct bpt *at_breakpoint(unsigned pc);
+static void bpt_cmds(void);
+
+extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
+extern void printf(const char *fmt, ...);
+extern int putchar(int ch);
+extern int setjmp(u_int *);
+extern void longjmp(u_int *, int);
+
+#define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+
+static char *help_string = "\
+Commands:\n\
+  d	dump bytes\n\
+  dc	dump characters\n\
+  di	dump instructions\n\
+  df	dump float values\n\
+  dd	dump double values\n\
+  e	print exception information\n\
+  h	dump hash table\n\
+  m	examine/change memory\n\
+  mm	move a block of memory\n\
+  ms	set a block of memory\n\
+  md	compare two blocks of memory\n\
+  r	print registers\n\
+  S	print special registers\n\
+  t	print backtrace\n\
+  x	exit monitor\n\
+";
+
+static int xmon_trace;
+#define SSTEP	1		/* stepping because of 's' command */
+#define BRSTEP	2		/* stepping over breakpoint */
+
+void
+xmon(struct pt_regs *excp)
+{
+	struct pt_regs regs;
+	int msr, cmd;
+
+	printk("Entering xmon kernel debugger.\n");
+	
+	if (excp == NULL) {
+		asm volatile ("stw	0,0(%0)\n\
+			lwz	0,0(1)\n\
+			stw	0,4(%0)\n\
+			stmw	2,8(%0)" : : "r" (®s));
+		regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
+		regs.msr = get_msr();
+		regs.ctr = get_ctr();
+		regs.xer = get_xer();
+		regs.ccr = get_cr();
+		regs.trap = 0;
+		excp = ®s;
+	}
+
+	msr = get_msr();
+	set_msr(msr & ~0x8000);	/* disable interrupts */
+	remove_bpts();
+	excprint(excp);
+	cmd = cmds(excp);
+	if (cmd == 's') {
+		xmon_trace = SSTEP;
+		excp->msr |= 0x400;
+	} else if (at_breakpoint(excp->nip)) {
+		xmon_trace = BRSTEP;
+		excp->msr |= 0x400;
+	} else {
+		xmon_trace = 0;
+		insert_bpts();
+	}
+	set_msr(msr);		/* restore interrupt enable */
+}
+
+void
+xmon_irq(int irq, void *d, struct pt_regs *regs)
+{
+	printf("Keyboard interrupt\n");
+	xmon(regs);
+}
+
+int
+xmon_bpt(struct pt_regs *regs)
+{
+	struct bpt *bp;
+
+	bp = at_breakpoint(regs->nip);
+	if (!bp)
+		return 0;
+	if (bp->count) {
+		--bp->count;
+		remove_bpts();
+		excprint(regs);
+		xmon_trace = BRSTEP;
+		regs->msr |= 0x400;
+	} else {
+		xmon(regs);
+	}
+	return 1;
+}
+
+int
+xmon_sstep(struct pt_regs *regs)
+{
+	if (!xmon_trace)
+		return 0;
+	if (xmon_trace == BRSTEP) {
+		xmon_trace = 0;
+		insert_bpts();
+	} else {
+		xmon(regs);
+	}
+	return 1;
+}
+
+int
+xmon_dabr_match(struct pt_regs *regs)
+{
+	if (dabr.enabled && dabr.count) {
+		--dabr.count;
+		remove_bpts();
+		excprint(regs);
+		xmon_trace = BRSTEP;
+		regs->msr |= 0x400;
+	} else {
+		dabr.instr = regs->nip;
+		xmon(regs);
+	}
+	return 1;
+}
+
+int
+xmon_iabr_match(struct pt_regs *regs)
+{
+	if (iabr.enabled && iabr.count) {
+		--iabr.count;
+		remove_bpts();
+		excprint(regs);
+		xmon_trace = BRSTEP;
+		regs->msr |= 0x400;
+	} else {
+		xmon(regs);
+	}
+	return 1;
+}
+
+static struct bpt *
+at_breakpoint(unsigned pc)
+{
+	int i;
+	struct bpt *bp;
+
+	if (dabr.enabled && pc == dabr.instr)
+		return &dabr;
+	if (iabr.enabled && pc == iabr.address)
+		return &iabr;
+	bp = bpts;
+	for (i = 0; i < NBPTS; ++i, ++bp)
+		if (bp->enabled && pc == bp->address)
+			return bp;
+	return 0;
+}
+
+static void
+insert_bpts()
+{
+	int i;
+	struct bpt *bp;
+
+	bp = bpts;
+	for (i = 0; i < NBPTS; ++i, ++bp) {
+		if (!bp->enabled)
+			continue;
+		if (mread(bp->address, &bp->instr, 4) != 4
+		    || mwrite(bp->address, &bpinstr, 4) != 4) {
+			printf("Couldn't insert breakpoint at %x, disabling\n",
+			       bp->address);
+			bp->enabled = 0;
+		}
+	}
+	if (dabr.enabled)
+		set_dabr(dabr.address);
+	if (iabr.enabled)
+		set_iabr(iabr.address);
+}
+
+static void
+remove_bpts()
+{
+	int i;
+	struct bpt *bp;
+	unsigned instr;
+
+	set_dabr(0);
+	set_iabr(0);
+	bp = bpts;
+	for (i = 0; i < NBPTS; ++i, ++bp) {
+		if (!bp->enabled)
+			continue;
+		if (mread(bp->address, &instr, 4) == 4
+		    && instr == bpinstr
+		    && mwrite(bp->address, &bp->instr, 4) != 4)
+			printf("Couldn't remove breakpoint at %x\n",
+			       bp->address);
+	}
+}
+
+static char *last_cmd;
+
+/* Command interpreting routine */
+static int
+cmds(struct pt_regs *excp)
+{
+	int cmd;
+
+	last_cmd = NULL;
+	for(;;) {
+		printf("mon> ");
+		fflush(stdout);
+		flush_input();
+		termch = 0;
+		cmd = skipbl();
+		if( cmd == '\n' ) {
+			if (last_cmd == NULL)
+				continue;
+			take_input(last_cmd);
+			last_cmd = NULL;
+			cmd = inchar();
+		}
+		switch (cmd) {
+		case 'm':
+			cmd = inchar();
+			switch (cmd) {
+			case 'm':
+			case 's':
+			case 'd':
+				memops(cmd);
+				break;
+			case 'l':
+				memlocate();
+				break;
+			case 'z':
+				memzcan();
+				break;
+			default:
+				termch = cmd;
+				memex();
+			}
+			break;
+		case 'd':
+			dump();
+			break;
+		case 'r':
+			if (excp != NULL)
+				prregs(excp);	/* print regs */
+			break;
+		case 'e':
+			if (excp == NULL)
+				printf("No exception information\n");
+			else
+				excprint(excp);
+			break;
+		case 'S':
+			super_regs();
+			break;
+		case 't':
+			backtrace(excp);
+			break;
+#if 0
+		case 'f':
+			openforth();
+			break;
+#endif
+		case 'h':
+			dump_hash_table();
+			break;
+		case 's':
+		case 'x':
+		case EOF:
+			return cmd;
+		case '?':
+			printf(help_string);
+			break;
+		default:
+			printf("Unrecognized command: ");
+			if( ' ' < cmd && cmd <= '~' )
+				putchar(cmd);
+			else
+				printf("\\x%x", cmd);
+			printf(" (type ? for help)\n");
+			break;
+		case 'b':
+			bpt_cmds();
+			break;
+		}
+	}
+}
+
+static void
+bpt_cmds(void)
+{
+	int cmd;
+	unsigned a;
+	int mode, i;
+	struct bpt *bp;
+
+	cmd = inchar();
+	switch (cmd) {
+	case 'd':
+		mode = 7;
+		cmd = inchar();
+		if (cmd == 'r')
+			mode = 5;
+		else if (cmd == 'w')
+			mode = 6;
+		else
+			termch = cmd;
+		dabr.address = 0;
+		dabr.count = 0;
+		dabr.enabled = scanhex(&dabr.address);
+		scanhex(&dabr.count);
+		if (dabr.enabled)
+			dabr.address = (dabr.address & ~7) | mode;
+		break;
+	case 'i':
+		iabr.address = 0;
+		iabr.count = 0;
+		iabr.enabled = scanhex(&iabr.address);
+		if (iabr.enabled)
+			iabr.address |= 3;
+		scanhex(&iabr.count);
+		break;
+	case 'c':
+		if (!scanhex(&a)) {
+			/* clear all breakpoints */
+			for (i = 0; i < NBPTS; ++i)
+				bpts[i].enabled = 0;
+			iabr.enabled = 0;
+			dabr.enabled = 0;
+			printf("All breakpoints cleared\n");
+		} else {
+			bp = at_breakpoint(a);
+			if (bp == 0) {
+				printf("No breakpoint at %x\n", a);
+			} else {
+				bp->enabled = 0;
+			}
+		}
+		break;
+	default:
+		termch = cmd;
+		if (!scanhex(&a)) {
+			/* print all breakpoints */
+			printf("type  address   count\n");
+			if (dabr.enabled) {
+				printf("data %.8x %8x [", dabr.address & ~7,
+				       dabr.count);
+				if (dabr.address & 1)
+					printf("r");
+				if (dabr.address & 2)
+					printf("w");
+				printf("]\n");
+			}
+			if (iabr.enabled)
+				printf("inst %.8x %8x\n", iabr.address & ~3,
+				       iabr.count);
+			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+				if (bp->enabled)
+					printf("trap %.8x %8x\n", bp->address,
+					       bp->count);
+			break;
+		}
+		bp = at_breakpoint(a);
+		if (bp == 0) {
+			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+				if (!bp->enabled)
+					break;
+			if (bp >= &bpts[NBPTS]) {
+				printf("Sorry, no free breakpoints\n");
+				break;
+			}
+		}
+		bp->enabled = 1;
+		bp->address = a;
+		bp->count = 0;
+		scanhex(&bp->count);
+		break;
+	}
+}
+
+static void
+backtrace(struct pt_regs *excp)
+{
+	unsigned sp;
+	unsigned stack[2];
+	struct pt_regs regs;
+	extern char int_return, syscall_ret_1, syscall_ret_2;
+	extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
+
+	if (excp != NULL)
+		sp = excp->gpr[1];
+	else
+		sp = getsp();
+	scanhex(&sp);
+	scannl();
+	for (; sp != 0; sp = stack[0]) {
+		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+			break;
+		printf("%x ", stack[1]);
+		if (stack[1] == (unsigned) &int_return
+		    || stack[1] == (unsigned) &syscall_ret_1
+		    || stack[1] == (unsigned) &syscall_ret_2
+		    || stack[1] == (unsigned) &lost_irq_ret
+		    || stack[1] == (unsigned) &do_bottom_half_ret
+		    || stack[1] == (unsigned) &do_signal_ret) {
+			if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
+				break;
+			printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+			       regs.nip);
+			sp = regs.gpr[1];
+			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+				break;
+		}
+	}
+	printf("\n");
+}
+
+int
+getsp()
+{
+    int x;
+
+    asm("mr %0,1" : "=r" (x) :);
+    return x;
+}
+
+void
+excprint(struct pt_regs *fp)
+{
+	printf("vector: %x at pc = %x, msr = %x, sp = %x [%x]\n",
+	       fp->trap, fp->nip, fp->msr, fp->gpr[1], fp);
+	if ((fp->trap == 0x300) || (fp->trap == 0x600) || (fp->trap == 0x200))
+		printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
+	if (current)
+		printf("current = %x, pid = %d, comm = %s\n",
+		       current, current->pid, current->comm);
+}
+
+void
+prregs(struct pt_regs *fp)
+{
+	int n;
+	unsigned base;
+
+	if (scanhex(&base))
+		fp = (struct pt_regs *) base;
+	for (n = 0; n < 32; ++n)
+		printf("R%.2d = %.8x%s", n, fp->gpr[n],
+		       (n & 3) == 3? "\n": "   ");
+	printf("pc  = %.8x   msr = %.8x   lr  = %.8x   cr  = %.8x\n",
+	       fp->nip, fp->msr, fp->link, fp->ccr);
+	printf("ctr = %.8x   xer = %.8x   trap = %4x\n",
+	       fp->ctr, fp->xer, fp->trap);
+}
+
+unsigned int
+read_spr(int n)
+{
+    unsigned int instrs[2];
+    int (*code)(void);
+
+    instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+    instrs[1] = 0x4e800020;
+    store_inst(instrs);
+    store_inst(instrs+1);
+    code = (int (*)(void)) instrs;
+    return code();
+}
+
+void
+write_spr(int n, unsigned int val)
+{
+    unsigned int instrs[2];
+    int (*code)(unsigned int);
+
+    instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+    instrs[1] = 0x4e800020;
+    store_inst(instrs);
+    store_inst(instrs+1);
+    code = (int (*)(unsigned int)) instrs;
+    code(val);
+}
+
+static unsigned int regno;
+extern char exc_prolog;
+extern char dec_exc;
+
+void
+super_regs()
+{
+	int i, cmd;
+	unsigned val;
+
+	cmd = skipbl();
+	if (cmd == '\n') {
+		printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
+		printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
+		       get_sprg2(), get_sprg3());
+		printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
+		printf("sr0-15 =");
+		for (i = 0; i < 16; ++i)
+			printf(" %x", get_sr(i));
+		printf("\n");
+		asm("mr %0,1" : "=r" (i) :);
+		printf("sp = %x ", i);
+		asm("mr %0,2" : "=r" (i) :);
+		printf("toc = %x\n", i);
+		return;
+	}
+
+	scanhex(®no);
+	switch (cmd) {
+	case 'w':
+		val = read_spr(regno);
+		scanhex(&val);
+		write_spr(regno, val);
+		/* fall through */
+	case 'r':
+		printf("spr %x = %x\n", regno, read_spr(regno));
+		break;
+	case 's':
+		val = get_sr(regno);
+		scanhex(&val);
+		set_sr(regno, val);
+		break;
+	case 'm':
+		val = get_msr();
+		scanhex(&val);
+		set_msr(val);
+		break;
+	}
+	scannl();
+}
+
+#if 0
+static void
+openforth()
+{
+    int c;
+    char *p;
+    char cmd[1024];
+    int args[5];
+    extern int (*prom_entry)(int *);
+
+    p = cmd;
+    c = skipbl();
+    while (c != '\n') {
+	*p++ = c;
+	c = inchar();
+    }
+    *p = 0;
+    args[0] = (int) "interpret";
+    args[1] = 1;
+    args[2] = 1;
+    args[3] = (int) cmd;
+    (*prom_entry)(args);
+    printf("\n");
+    if (args[4] != 0)
+	printf("error %x\n", args[4]);
+}
+#endif
+
+static void
+dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
+{
+	extern void *Hash;
+	extern unsigned long Hash_size;
+	unsigned *htab = Hash;
+	unsigned hsize = Hash_size;
+	unsigned v, hmask, va, last_va;
+	int found, last_found, i;
+	unsigned *hg, w1, last_w2, last_va0;
+
+	last_found = 0;
+	hmask = hsize / 64 - 1;
+	va = start;
+	start = (start >> 12) & 0xffff;
+	end = (end >> 12) & 0xffff;
+	for (v = start; v < end; ++v) {
+		found = 0;
+		hg = htab + (((v ^ seg) & hmask) * 16);
+		w1 = 0x80000000 | (seg << 7) | (v >> 10);
+		for (i = 0; i < 8; ++i, hg += 2) {
+			if (*hg == w1) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			w1 ^= 0x40;
+			hg = htab + ((~(v ^ seg) & hmask) * 16);
+			for (i = 0; i < 8; ++i, hg += 2) {
+				if (*hg == w1) {
+					found = 1;
+					break;
+				}
+			}
+		}
+		if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
+			if (last_found) {
+				if (last_va != last_va0)
+					printf(" ... %x", last_va);
+				printf("\n");
+			}
+			if (found) {
+				printf("%x to %x", va, hg[1]);
+				last_va0 = va;
+			}
+			last_found = found;
+		}
+		if (found) {
+			last_w2 = hg[1] & ~0x180;
+			last_va = va;
+		}
+		va += 4096;
+	}
+	if (last_found)
+		printf(" ... %x\n", last_va);
+}
+static unsigned hash_ctx;
+static unsigned hash_start;
+static unsigned hash_end;
+
+static void
+dump_hash_table()
+{
+	int seg;
+	unsigned seg_start, seg_end;
+
+	hash_ctx = 0;
+	hash_start = 0;
+	hash_end = 0xfffff000;
+	scanhex(&hash_ctx);
+	scanhex(&hash_start);
+	scanhex(&hash_end);
+	printf("Mappings for context %x\n", hash_ctx);
+	seg_start = hash_start;
+	for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
+		seg_end = (seg << 28) | 0x0ffff000;
+		if (seg_end > hash_end)
+			seg_end = hash_end;
+		dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
+		seg_start = seg_end + 0x1000;
+	}
+}
+
+/*
+ * Stuff for reading and writing memory safely
+ */
+extern inline void sync(void)
+{
+	asm volatile("sync; isync");
+}
+
+extern inline void __delay(unsigned int loops)
+{
+	if (loops != 0)
+		__asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
+				     "r" (loops) : "ctr");
+}
+
+int
+mread(unsigned adrs, void *buf, int size)
+{
+	volatile int n;
+	char *p, *q;
+
+	n = 0;
+	if( setjmp(bus_error_jmp) == 0 ){
+		debugger_fault_handler = handle_fault;
+		sync();
+		p = (char *) adrs;
+		q = (char *) buf;
+		switch (size) {
+		case 2: *(short *)q = *(short *)p;	break;
+		case 4: *(int *)q = *(int *)p;		break;
+		default:
+			for( ; n < size; ++n ) {
+				*q++ = *p++;
+				sync();
+			}
+		}
+		sync();
+		/* wait a little while to see if we get a machine check */
+		__delay(200);
+		n = size;
+	}
+	debugger_fault_handler = 0;
+	return n;
+}
+
+int
+mwrite(unsigned adrs, void *buf, int size)
+{
+	volatile int n;
+	char *p, *q;
+
+	n = 0;
+	if( setjmp(bus_error_jmp) == 0 ){
+		debugger_fault_handler = handle_fault;
+		sync();
+		p = (char *) adrs;
+		q = (char *) buf;
+		switch (size) {
+		case 2: *(short *)p = *(short *)q;	break;
+		case 4: *(int *)p = *(int *)q;		break;
+		default:
+			for( ; n < size; ++n ) {
+				*p++ = *q++;
+				sync();
+			}
+		}
+		sync();
+		n = size;
+	} else {
+		printf("*** Error writing address %x\n", adrs + n);
+	}
+	debugger_fault_handler = 0;
+	return n;
+}
+
+static int fault_type;
+static char *fault_chars[] = { "--", "**", "##" };
+
+static void
+handle_fault(struct pt_regs *regs)
+{
+	fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
+	longjmp(bus_error_jmp, 1);
+}
+
+#define SWAP(a, b, t)	((t) = (a), (a) = (b), (b) = (t))
+
+void
+byterev(unsigned char *val, int size)
+{
+	int t;
+	
+	switch (size) {
+	case 2:
+		SWAP(val[0], val[1], t);
+		break;
+	case 4:
+		SWAP(val[0], val[3], t);
+		SWAP(val[1], val[2], t);
+		break;
+	}
+}
+
+static int brev;
+static int mnoread;
+
+void
+memex()
+{
+    int cmd, inc, i, nslash;
+    unsigned n;
+    unsigned char val[4];
+
+    last_cmd = "m\n";
+    scanhex(&adrs);
+    while ((cmd = skipbl()) != '\n') {
+	switch( cmd ){
+	case 'b':	size = 1;	break;
+	case 'w':	size = 2;	break;
+	case 'l':	size = 4;	break;
+	case 'r': 	brev = !brev;	break;
+	case 'n':	mnoread = 1;	break;
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 05'
echo 'File patch-2.3.4 is continued in part 06'
echo 06 > _shar_seq_.tmp
#!/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 50 - 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.3.4 ==============
if test -f 'patch-2.3.4' -a X"$1" != X"-c"; then
        echo 'x - skipping patch-2.3.4 (File already exists)'
        rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.3.4 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.3.4' &&
diff -u --recursive --new-file v2.3.3/linux/CREDITS linux/CREDITS
--- v2.3.3/linux/CREDITS	Mon May 17 09:55:20 1999
+++ linux/CREDITS	Mon May 24 22:47:43 1999
@@ -767,11 +767,8 @@
X S: The Netherlands
X 
X N: Kai Harrekilde-Petersen
-E: k...@dolphinics.no
+E: k...@olicom.dk
X D: Original author of the ftape-HOWTO, i82078 fdc detection code.
-S: Peder Holters vei 13
-S: 1168 Oslo
-S: Norway
X 
X N: Andrew Haylett
X E: a...@primag.co.uk
@@ -1439,8 +1436,8 @@
X S: Germany
X 
X N: David Mosberger-Tang
-E: David.M...@acm.org
-D: Linux/Alpha
+E: dav...@hpl.hp.com if IA-64 related, else David.M...@acm.org
+D: Linux/Alpha and Linux/ia64
X S: 35706 Runckel Lane
X S: Fremont, California 94536
X S: USA
diff -u --recursive --new-file v2.3.3/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.3/linux/Documentation/Configure.help	Mon May 17 09:55:20 1999
+++ linux/Documentation/Configure.help	Wed May 26 10:01:43 1999
@@ -3110,6 +3110,44 @@
X   The module will be called af_spx.o. If you want to compile it as a
X   module, say M here and read Documentation/modules.txt.
X 
+DECnet networking
+CONFIG_DECNET
+  The DECnet networking protocol was used in many products made by
+  Digital (now Compaq). It provides reliable stream and sequenced
+  packet communications over which run a variety of services similar
+  to those which run over TCP/IP.
+
+  To find some tools to use with the kernel layer support, please
+  look at Patrick Caulfield's web site: 
+  http://linux.dreamtime.org/decnet/
+
+  More detailed documentation is available in the
+  Documentation/networking/decnet.txt file.
+
+  Be sure to turn on the CONFIG_PROCFS and CONFIG_SYSCTL options
+  when using DECnet, since you will need sysctl support to aid in
+  configuration at run time.
+
+DECnet SIOCFIGCONF support
+CONFIG_DECNET_SIOCGIFCONF
+   This option should only be turned on if you are really sure that
+   you know what you are doing. It can break other applications which
+   use this system call and the proper way to get the information
+   provided by this call is to use rtnetlink.
+
+DECnet Router Support
+CONFIG_DECNET_ROUTER
+   Add support for turning your DECnet Endnode into a level 1 or 2
+   router. This is an unfinished option for developers only. If you
+   do turn it on, then make sure you also have rtnetlink configured
+   in, since thats the only current method of configuration.
+
+DECnet Raw Socket Support
+CONFIG_DECNET_RAW
+   Add support for the SOCK_RAW type under DECnet. Used by userland
+   routing programs to receive routing messages from the kernel and
+   also as a general debugging aid to see whats going on "under the hood".
+
X AppleTalk DDP
X CONFIG_ATALK
X   AppleTalk is the way Apple computers speak to each other on a
@@ -7525,6 +7563,18 @@
X   Say Y here if you want to try writing to UFS partitions. This is
X   experimental, so you should back up your UFS partitions beforehand.
X 
+EFS filesystem support (experimental)
+CONFIG_EFS_FS
+  EFS is the filesystem used for CDROMs and filesystems by SGI's IRIX.
+  This implementation only offers read-only access. If you don't know
+  what all this is about, it's safe to say N. For more information
+  about EFS see its homepage at http://aeschi.ch.eu.org/efs/.
+
+SGI disklabel support
+CONFIG_SGI_DISKLABEL
+  Say Y to this only if you plan on mounting disks with SGI disklabels.
+  This is not required to mount EFS-format CDROMs.
+
X BSD disklabel (FreeBSD partition tables) support
X CONFIG_BSD_DISKLABEL
X   FreeBSD uses its own hard disk partition scheme on your PC. It
@@ -11559,6 +11609,64 @@
X   This is the driver for the serial ports on the BVME4000 and BVME6000
X   boards from BVM Ltd.  Everyone using one of these boards should say
X   Y here.
+
+Universal Serial Bus (USB) Support (Experimental)
+CONFIG_USB
+  This will enable support for the Universal Serial Bus (USB).  USB 
+  allows you to connect up to 127 external devices such as keyboards, 
+  mice, printers and modems to your computer through a USB connector.
+  This code can also be built as a module (i.e. code outside the 
+  kernel that can be added and removed at runtime), consult 
+  Documentation/modules.txt for more information.
+
+UHCI (intel PIIX4 and others) support
+CONFIG_USB_UHCI
+  The UHCI is the USB host controller for many computers, and is built
+  into all recent boards with intel PCI chipsets. This driver is
+  needed for these motherboards to support USB.
+
+OHCI (compaq and some others) support
+CONFIG_USB_OHCI
+  The OHCI (Open Host Controller Interface) is the USB host controller
+  on most non-Intel architectures, several USB-adding PCI cards, and
+  is on several x86 compatibles with non-Intel chipsets. This driver
+  is needed for these motherboards to support USB. There is presently
+  two OHCI drivers in development. Say 'N' here if you would like to
+  compile the other OHCI driver into the linux kernel.
+
+OHCI-HCD (other OHCI opt. Virt. Root Hub) support
+CONFIG_USB_OHCI_HCD
+  The OHCI (Open Host Controller Interface) is the USB host controller
+  on most non-Intel architectures, several USB-adding PCI cards, and
+  is on several x86 compatibles with non-Intel chipsets. This driver
+  is needed for these motherboards to support USB. There is presently
+  two OHCI drivers in development. 
+
+USB hub support
+CONFIG_USB_HUB
+  To expand beyond the USB ports on the computer, a device called a 
+  hub is used. This driver supports hubs, allowing them to be used. 
+  Say 'Y'
+
+USB mouse support
+CONFIG_USB_MOUSE  
+  This driver allows mice to work under the USB stack. It currently
+  patches into /dev/ps2aux, although it does not require the ps2 
+  mouse code to be included in the kernel as well.
+
+USB keyboard support
+CONFIG_USB_KBD
+  This driver allows usb keyboards to work under the USB stack.
+
+USB audio parsing support (Preliminary)
+CONFIG_USB_AUDIO
+  This driver will eventually handle audio devices, such 
+  as USB speakers.
+
+USB Abstract Control Model support (Preliminary)
+CONFIG_USB_ACM
+  This driver allows for devices which support the Abstract Control Model,
+  including many USB-based modems, ISDN adapters, and network adapters.
X 
X #
X # A couple of things I keep forgetting:
diff -u --recursive --new-file v2.3.3/linux/Documentation/filesystems/isofs.txt linux/Documentation/filesystems/isofs.txt
--- v2.3.3/linux/Documentation/filesystems/isofs.txt	Wed Jun 24 14:30:07 1998
+++ linux/Documentation/filesystems/isofs.txt	Wed May 26 10:01:43 1999
@@ -27,3 +27,5 @@
X   nojoliet      Ignore Joliet extensions if they are present.
X   norock        Ignore Rock Ridge extensions if they are present.
X   unhide        Show hidden files.
+  session=x     Select number of session on multisession CD
+  sbsector=xxx  Session begins from sector xxx
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/HiSax.cert linux/Documentation/isdn/HiSax.cert
--- v2.3.3/linux/Documentation/isdn/HiSax.cert	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/HiSax.cert	Sun May 23 10:03:41 1999
@@ -0,0 +1,76 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+First:
+
+    HiSax 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.
+
+However, if you wish to modify the HiSax sources, please note the following:
+
+HiSax has passed the ITU approval test suite with ELSA Quickstep ISDN cards.
+The certification is only valid for the combination of the tested software
+version and the tested hardware. Any changes to the HiSax source code may
+therefore affect the certification.
+
+If you change the main files of the HiSax ISDN stack, the certification will
+become invalid. Because in most countries it is illegal to connect
+unapproved ISDN equipment to the public network, I have to guarantee that
+changes in HiSax do not affect the certification.
+
+In order to make a valid certification apparent to the user, I have built in
+some validation checks that are made during the make process. The HiSax main
+files are protected by md5 checksums and the md5sum file is pgp signed by
+myself:
+
+KeyID 1024/FF992F6D 1997/01/16 Karsten Keil <ke...@temic-ech.spacenet.de>
+Key fingerprint = 92 6B F7 58 EE 86 28 C8  C4 1A E6 DC 39 89 F2 AA
+
+Only if the checksums are OK, and the signature of the file
+"drivers/isdn/hisax/md5sums.asc" match, is the certification valid; a
+message confirming this is then displayed during the hisax init process.
+
+The affected files are:
+
+drivers/isdn/hisax/isac.c
+drivers/isdn/hisax/isdnl1.c
+drivers/isdn/hisax/isdnl2.c
+drivers/isdn/hisax/isdnl3.c
+drivers/isdn/hisax/tei.c
+drivers/isdn/hisax/callc.c
+drivers/isdn/hisax/l3dss1.c
+drivers/isdn/hisax/l3_1tr6.c
+drivers/isdn/hisax/cert.c
+drivers/isdn/hisax/elsa.c
+
+Please send any changes, bugfixes and patches to me rather than implementing
+them directly into the HiSax sources.
+
+This does not reduce your rights granted by the GNU General Public License.
+If you wish to change the sources, go ahead; but note that then the
+certification is invalid even if you use ELSA Quickstep cards.
+
+Here are the certification registration numbers for ELSA Quickstep cards:
+German   D133361J CETECOM ICT Services GmbH 0682
+European D133362J CETECOM ICT Services GmbH 0682
+
+
+Karsten Keil
+ke...@isdn4linux.de
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3i
+Charset: noconv
+
+iQCVAwUBNj5OKDpxHvX/mS9tAQFHuQP/WeImlqCcDZ2d132yAvRBWFULlJoSf1P/
+c1lVTeaWvsSaY5Cu9hrKhXXhPzeEaitUbcUBPXdpzFWCA5CE902lnz7AhgRC+HF1
+0qiKgkZZyc/5HKasFymR1+IWSLw30GesP3Di/ZMR3NJi8SlY9PIjx7hnEMunGSRO
+1ufPvfWWuu8=
+=nGJk
+-----END PGP SIGNATURE-----
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/INTERFACE linux/Documentation/isdn/INTERFACE
--- v2.3.3/linux/Documentation/isdn/INTERFACE	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/isdn/INTERFACE	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-$Id: INTERFACE,v 1.8 1998/02/20 17:38:20 fritz Exp $
+$Id: INTERFACE,v 1.11 1999/03/02 12:14:51 armin Exp $
X 
X Description of the Interface between Linklevel and Hardwarelevel
X   of isdn4linux:
@@ -478,6 +478,14 @@
X       1           = At least one device matching this call (RING on ttyI).
X                     HL-driver may send ALERTING on the D-channel in this case.
X       2           = Call will be rejected.
+      3           = Incomplete number.
+                    The CalledNumber would match, if more digits are appended.
+                    This feature is needed for Number-Blocks assigned to
+                    a line. In this case, the LL driver should assemble the
+					CalledNumber by handling keypad protocol and try again
+					later with a longer CalledNumber.
+					HL drivers serving ordinary lines should interpret this
+					return code like 0 (nothing matches).
X       -1          = An error happened. (Invalid parameters for example.)
X 
X   ISDN_STAT_RUN:
@@ -526,7 +534,9 @@
X       driver      = driver-Id
X       command     = ISDN_STAT_BCONN
X       arg         = channel-number, locally to the driver. (starting with 0)
-      para        = unused.
+      para.num    = ASCII-String, containing type of connection (for analog
+		    modem only). This will be appended to the CONNECT message
+		    e.g. 14400/V.32bis
X 
X   ISDN_STAT_DHUP:
X 
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README linux/Documentation/isdn/README
--- v2.3.3/linux/Documentation/isdn/README	Wed May 20 18:54:34 1998
+++ linux/Documentation/isdn/README	Sun May 23 10:03:41 1999
@@ -31,7 +31,7 @@
X    This mailinglist is bidirectionally gated to the newsgroup
X 
X      de.alt.comm.isdn4linux
-   
+
X   There is also a well maintained FAQ (both english and german) available
X   at ftp.franken.de in /pub/isdn4linux/FAQ/
X   This FAQ is also available at http://www.lrz-muenchen.de/~ui161ab/www/isdn/
@@ -41,11 +41,11 @@
X   In the following Text, the terms MSN and EAZ are used.
X 
X   MSN is the abbreviation for (M)ultiple(S)ubscriber(N)umber, and applies
-  to Euro(EDSS1)-type lines. Usually it is simply the phone-number.
+  to Euro(EDSS1)-type lines. Usually it is simply the phone number.
X 
X   EAZ is the abbreviation of (E)ndgeraete(A)uswahl(Z)iffer and
X   applies to German 1TR6-type lines. This is a one-digit string,
-  simply appended to the base phone-number
+  simply appended to the base phone number
X 
X   The internal handling is nearly identical, so replace the appropriate
X   term to that one, which applies to your local ISDN-environment.
@@ -56,13 +56,13 @@
X   A low-level-driver can register itself through an interface (which is
X   defined in isdnif.h) and gets assigned a slot.
X   The following char-devices are made available for each channel:
-  
+
X   A raw-control-device with the following functions:
X      write: raw D-channel-messages (format: depends on driver).
X      read:  raw D-channel-messages (format: depends on driver).
X      ioctl: depends on driver, i.e. for the ICN-driver, the base-address of
X             the ports and the shared memory on the card can be set and read
-            also the boot-code and the protocol software can be loaded into 
+            also the boot-code and the protocol software can be loaded into
X             the card.
X 
X    O N L Y !!!  for debugging (no locking against other devices):
@@ -74,38 +74,38 @@
X 
X    128 tty-devices (64 cuix and 64 ttyIx) with integrated modem-emulator:
X    The functionality is almost the same as that of a serial device
-   (the line-discs are handled by the kernel), which lets you run 
-   SLIP, CSLIP and asynchronous PPP through the devices. We have tested 
+   (the line-discs are handled by the kernel), which lets you run
+   SLIP, CSLIP and asynchronous PPP through the devices. We have tested
X    Seyon, minicom, CSLIP (uri-dip) PPP and mgetty (compiled with NO_FAX),
X    XCept.
X 
X    The modem-emulation supports the following:
X            1.3.1 Commands:
X 
-               ATA	Answer incoming call.
-	       ATD<No.> Dial, the number may contain:
+               ATA      Answer incoming call.
+               ATD<No.> Dial, the number may contain:
X                         [0-9] and [,#.*WPT-S]
X                         the latter are ignored until 'S'.
-                        The 'S' must precede the number, if 
+                        The 'S' must precede the number, if
X                         the line is a SPV (German 1TR6).
-               ATE0	Echo off.
-	       ATE1     Echo on (default).
+               ATE0     Echo off.
+               ATE1     Echo on (default).
X                ATH      Hang-up.
-	       ATH1     Off hook (ignored).
+               ATH1     Off hook (ignored).
X                ATH0     Hang-up.
-	       ATI      Return "ISDN for Linux...".
+               ATI      Return "ISDN for Linux...".
X                ATI0        "
X                ATI1        "
-	       ATI2     Report of last connection.
+               ATI2     Report of last connection.
X                ATO      On line (data mode).
X                ATQ0     Enable result codes (default).
X                ATQ1     Disable result codes (default).
-               ATSx=y	Set register x to y.
-	       ATSx?    Show contents of register x.
+               ATSx=y   Set register x to y.
+               ATSx?    Show contents of register x.
X                ATV0     Numeric responses.
X                ATV1     English responses (default).
-	       ATZ      Load registers and EAZ/MSN from Profile.
-	       AT&Bx    Set Send-Packet-size to x (max. 4000)
+               ATZ      Load registers and EAZ/MSN from Profile.
+               AT&Bx    Set Send-Packet-size to x (max. 4000)
X                         The real packet-size may be limited by the
X                         low-level-driver used. e.g. the HiSax-Module-
X                         limit is 2000. You will get NO Error-Message,
@@ -114,13 +114,13 @@
X                         driver may not be selected (see "Automatic
X                         Assignment") however the size of outgoing packets
X                         will be limited correctly.
-	       AT&D0    Ignore DTR
-	       AT&D2    DTR-low-edge: Hang up and return to 
+               AT&D0    Ignore DTR
+               AT&D2    DTR-low-edge: Hang up and return to
X                         command mode (default).
X                AT&D3    Same as AT&D2 but also resets all registers.
-	       AT&Ex    Set the EAZ/MSN for this channel to x.
-	       AT&F     Reset all registers and profile to "factory-defaults"
-	       AT&Rx    Select V.110 bitrate adaption.
+               AT&Ex    Set the EAZ/MSN for this channel to x.
+               AT&F     Reset all registers and profile to "factory-defaults"
+               AT&Rx    Select V.110 bitrate adaption.
X                         This command enables V.110 protocol with 9600 baud
X                         (x=9600), 19200 baud (x=19200) or 38400 baud
X                         (x=38400). A value of x=0 disables V.110 switching
@@ -142,24 +142,24 @@
X                             The value 198 is choosen arbitrarily. Users
X                             _MUST_ negotiate this value before establishing
X                             a connection.
-	       AT&Sx    Set window-size (x = 1..8) (not yet implemented)
-	       AT&V     Show all settings.
+               AT&Sx    Set window-size (x = 1..8) (not yet implemented)
+               AT&V     Show all settings.
X                AT&W0    Write registers and EAZ/MSN to profile. See also
X                         iprofd (5.c in this README).
-               AT&X0	BTX-mode and T.70-mode off (default)
-	       AT&X1    BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
-	       AT&X2    T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
+               AT&X0    BTX-mode and T.70-mode off (default)
+               AT&X1    BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
+               AT&X2    T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
X 
X            For voice-mode commands refer to README.audio
X 
-	   1.3.2 Escape sequence:
+           1.3.2 Escape sequence:
X                During a connection, the emulation reacts just like
X                a normal modem to the escape sequence <DELAY>+++<DELAY>.
-	       (The escape character - default '+' - can be set in the
+               (The escape character - default '+' - can be set in the
X                register 2).
-               The DELAY must at least be 1.5 seconds long and delay 
+               The DELAY must at least be 1.5 seconds long and delay
X                between the escape characters must not exceed 0.5 seconds.
-     
+
X            1.3.3 Registers:
X 
X               Nr.  Default  Description
@@ -172,7 +172,7 @@
X               4    10       Line feed character (ASCII).
X               5    8        Backspace character (ASCII).
X               6    3        Delay in seconds before dialing.
-              7    60       Wait for carrier (ignored).
+              7    60       Wait for carrier.
X               8    2        Pause time for comma (ignored)
X               9    6        Carrier detect time (ignored)
X              10    7        Carrier loss to disconnect time (ignored).
@@ -203,8 +203,8 @@
X                                       1 = T.70 protocol (Only for BTX!) on
X                             Bit 2:    0 = Don't hangup on DTR low.
X                                       1 = Hangup on DTR low.
-			    Bit 3:    0 = Standard response messages
-				      1 = Extended response messages
+                            Bit 3:    0 = Standard response messages
+                                      1 = Extended response messages
X                             Bit 4:    0 = CALLER NUMBER before every RING.
X                                       1 = CALLER NUMBER after first RING.
X                             Bit 5:    0 = T.70 extended protocol off
@@ -215,18 +215,19 @@
X                                           an incoming call happened (RING) and
X                                           the remote party hung up before any
X                                           local ATA was given.
-	     14   0         Layer-2 protocol:
-				      0 = X75/LAPB with I-frames
-				      1 = X75/LAPB with UI-frames
+             14   0         Layer-2 protocol:
+                                      0 = X75/LAPB with I-frames
+                                      1 = X75/LAPB with UI-frames
X                                       2 = X75/LAPB with BUI-frames
X                                       3 = HDLC
X                                       4 = Transparent (audio)
X                                       7 = V.110, 9600 baud
X                                       8 = V.110, 19200 baud
X                                       9 = V.110, 38400 baud
+                                     10 = Analog Modem (only if hardware supports this)
X              15   0         Layer-3 protocol: (at the moment always 0)
X                                       0 = transparent
-	     16   250       Send-Packet-size/16
+             16   250       Send-Packet-size/16
X              17   8         Window-size (not yet implemented)
X              18   4         Bit coded register, Service-Octet-1 to accept,
X                             or to be used on dialout:
@@ -262,7 +263,7 @@
X 
X   All inactive physical lines are listening to all EAZs for incoming
X   calls and are NOT assigned to a specific tty or network interface.
-  When an incoming call is detected, the driver looks first for a network 
+  When an incoming call is detected, the driver looks first for a network
X   interface and then for an opened tty which:
X 
X   1. is configured for the same EAZ.
@@ -270,7 +271,7 @@
X   3. (only for network interfaces if the security flag is set)
X      contains the caller number in its access list.
X   4. Either the channel is not bound exclusively to another Net-interface, or
-     it is bound AND the other checks apply to exactly this Interface.
+     it is bound AND the other checks apply to exactly this interface.
X      (For usage of the bind-features, refer to the isdnctrl-man-page)
X 
X   Only when a matching interface or tty is found is the call accepted
@@ -301,7 +302,7 @@
X   Always use the latest module utilities. The current version is
X   named in Documentation/Changes. Some old versions of insmod
X   are not capable of setting the driver-Ids correctly.
- 
+
X 3. Lowlevel-driver configuration.
X 
X    Configuration depends on how the drivers are built. See the
@@ -310,7 +311,7 @@
X 4. Device-inodes
X 
X    The major and minor numbers and their names are described in
-   Documentation/devices.txt. The major-numbers are:
+   Documentation/devices.txt. The major numbers are:
X 
X      43 for the ISDN-tty's.
X      44 for the ISDN-callout-tty's.
@@ -350,45 +351,64 @@
X    g) Set the timeout for hang-up:
X        isdnctrl huptimeout isdn0 <timeout_in_seconds>
X 
-   h) additionally you may activate charge-hang-up (= Hang up before 
+   h) additionally you may activate charge-hang-up (= Hang up before
X       next charge-info, this only works, if your isdn-provider transmits
X       the charge-info during and after the connection):
X        isdnctrl chargehup isdn0 on
X 
-   i) Setup the interface with ifconfig as usual, and set a route to it.
+   i) Set the dial mode of the interface:
+       isdnctrl dialmode isdn0 auto
+      "off" means that you (or the system) cannot make any connection
+        (neither incoming or outgoing connections are possible). Use
+        this if you want to be sure that no connections will be made.
+      "auto" means that the interface is in auto-dial mode, and will
+        attempt to make a connection whenever a network data packet needs
+        the interface's link. Note that this can cause unexpected dialouts,
+        and lead to a high phone bill! Some daemons or other pc's that use
+        this interface can cause this.
+        Incoming connections are also possible.
+      "manual" is a dial mode created to prevent the unexpected dialouts.
+        In this mode, the interface will never make any connections on its
+        own. You must explicitly initiate a connection with "isdnctrl dial
+        isdn0". However, after an idle time of no traffic as configured for
+	the huptimeout value with isdnctrl, the connection _will_ be ended.
+	If you don't want any automatic hangup, set the huptimeout value to 0.
+        "manual" is the default.
X 
-   j) (optional) If you run X11 and have Tcl/Tk-wish Version 4.0, you can use
+   j) Setup the interface with ifconfig as usual, and set a route to it.
+
+   k) (optional) If you run X11 and have Tcl/Tk-wish version 4.0, you can use
X      the script tools/tcltk/isdnmon. You can add actions for line-status
X      changes. See the comments at the beginning of the script for how to
X      do that. There are other tty-based tools in the tools-subdirectory
X      contributed by Michael Knigge (imon), Volker Götz (imontty) and
X      Andreas Kool (isdnmon).
X 
-   k) For initial testing, you can set the verbose-level to 2 (default: 0).
+   l) For initial testing, you can set the verbose-level to 2 (default: 0).
X       Then all incoming calls are logged, even if they are not addressed
X       to one of the configured net-interfaces:
X       isdnctrl verbose 2
X 
-  Now you are ready! A ping to the set address should now result in a
-  dial-out (look at syslog kernel-messages).
-  The phone-numbers and EAZs can be assigned at any time with isdnctrl.
+  Now you are ready! A ping to the set address should now result in an
+  automatic dial-out (look at syslog kernel-messages).
+  The phone numbers and EAZs can be assigned at any time with isdnctrl.
X   You can add as many interfaces as you like with addif following the
-  directions above. Of course, there may be some limitations. But we have 
-  tested as many as 20 interfaces without any problem. However, if you 
-  don't give an interface name to addif, the  kernel will assign a name 
+  directions above. Of course, there may be some limitations. But we have
+  tested as many as 20 interfaces without any problem. However, if you
+  don't give an interface name to addif, the  kernel will assign a name
X   which starts with "eth". The number of "eth"-interfaces is limited by
X   the kernel.
X 
X 5. Additional options for isdnctrl:
X 
-   "isdnctrl secure <InterfaceName> on" 
+   "isdnctrl secure <InterfaceName> on"
X    Only incoming calls, for which the caller-id is listed in the access
X    list of the interface are accepted. You can add caller-id's With the
X    command "isdnctrl addphone <InterfaceName> in <caller-id>"
X    Euro-ISDN does not transmit the leading '0' of the caller-id for an
X    incoming call, therefore you should configure it accordingly.
X    If the real number for the dialout e.g. is "09311234567" the number
-   to configure here is "9311234567". The pattern-match function 
+   to configure here is "9311234567". The pattern-match function
X    works similar to the shell mechanism.
X 
X      ?     one arbitrary digit
@@ -398,23 +418,23 @@
X            a '^' as the first character in a list inverts the list
X 
X 
-   "isdnctrl secure <InterfaceName> off" 
+   "isdnctrl secure <InterfaceName> off"
X    Switch off secure operation (default).
X 
-   "isdnctrl ihup <InterfaceName> [on|off]" 
+   "isdnctrl ihup <InterfaceName> [on|off]"
X    Switch the hang-up-timer for incoming calls on or off.
X 
-   "isdnctrl eaz <InterfaceName>" 
+   "isdnctrl eaz <InterfaceName>"
X    Returns the EAZ of an interface.
X 
-   "isdnctrl delphone <InterfaceName> in|out <number>" 
+   "isdnctrl delphone <InterfaceName> in|out <number>"
X    Deletes a number from one of the access-lists of the interface.
X 
-   "isdnctrl delif <InterfaceName>" 
+   "isdnctrl delif <InterfaceName>"
X    Removes the interface (and possible slaves) from the kernel.
X    (You have to unregister it with "ifconfig <InterfaceName> down" before).
X 
-   "isdnctrl callback <InterfaceName> [on|off]" 
+   "isdnctrl callback <InterfaceName> [on|off]"
X    Switches an interface to callback-mode. In this mode, an incoming call
X    will be rejected and after this the remote-station will be called. If
X    you test this feature by using ping, some routers will re-dial very
@@ -435,14 +455,14 @@
X    only while an interface is down.
X 
X    At the moment the following values are supported:
- 
+
X    rawip    (Default) Selects raw-IP-encapsulation. This means, MAC-headers
-            are stripped off.  
+            are stripped off.
X    ip       IP with type-field. Same as IP but the type-field of the MAC-header
X             is preserved.
X    x25iface X.25 interface encapsulation (first byte semantics as defined in
-	    ../networking/x25-iface.txt). Use this for running the linux
-	    X.25 network protocol stack (AF_X25 sockets) on top of isdn.
+            ../networking/x25-iface.txt). Use this for running the linux
+            X.25 network protocol stack (AF_X25 sockets) on top of isdn.
X    cisco-h  A special-mode for communicating with a Cisco, which is configured
X             to do "hdlc"
X    ethernet No stripping. Packets are sent with full MAC-header.
@@ -454,7 +474,7 @@
X 
X 
X    NOTE:    x25iface encapsulation is currently experimental. Please
-	    read README.x25 for further details    
+            read README.x25 for further details
X 
X 
X    Watching packets, using standard-tcpdump will fail for all encapsulations
@@ -462,16 +482,16 @@
X    without MAC-header. A patch for tcpdump is included in the utility-package
X    mentioned above.
X 
-   "isdnctrl l2_prot <InterfaceName> <L2-ProtocolName>" 
-   Selects a layer-2-protocol. 
+   "isdnctrl l2_prot <InterfaceName> <L2-ProtocolName>"
+   Selects a layer-2-protocol.
X    (With the ICN-driver and the HiSax-driver, "x75i" and "hdlc" is available.
X    With other drivers, "x75ui", "x75bui", "x25dte", "x25dce" may be
X    possible too. See README.x25 for x25 related l2 protocols.)
X 
-   isdnctrl l3_prot <InterfaceName> <L3-ProtocolName> 
+   isdnctrl l3_prot <InterfaceName> <L3-ProtocolName>
X    The same for layer-3. (At the moment only "trans" is allowed)
X 
-   "isdnctrl list <InterfaceName>" 
+   "isdnctrl list <InterfaceName>"
X    Shows all parameters of an interface and the charge-info.
X    Try "all" as the interface name.
X 
@@ -479,13 +499,13 @@
X    Forces hangup of an interface.
X 
X    "isdnctrl bind <InterfaceName> <DriverId>,<ChannelNumber> [exclusive]"
-   If you are using more than one ISDN-Card, it is sometimes necessary to
-   dial out using a specific Card or even preserve a specific Channel for
-   Dialout of a specific net-interface. This can be done with the above
+   If you are using more than one ISDN card, it is sometimes necessary to
+   dial out using a specific card or even preserve a specific channel for
+   dialout of a specific net-interface. This can be done with the above
X    command. Replace <DriverId> by whatever you assigned while loading the
-   module. The <ChannelNumber> is counting from zero. The upper Limit
-   depends on the card used. At the Moment no card supports more than
-   2 Channels, so the upper limit is one.
+   module. The <ChannelNumber> is counted from zero. The upper limit
+   depends on the card used. At the moment no card supports more than
+   2 channels, so the upper limit is one.
X 
X    "isdnctrl unbind <InterfaceName>"
X    unbinds a previously bound interface.
@@ -494,10 +514,10 @@
X    If switched on, isdn4linux replies a REJECT to incoming calls, it
X    cannot match to any configured interface.
X    If switched off, nothing happens in this case.
-   You normally should NOT enable this feature, if the ISDN-adaptor is not
-   the only device, connected to the S0-bus. Otherwise it could happen, that
+   You normally should NOT enable this feature, if the ISDN adapter is not
+   the only device connected to the S0-bus. Otherwise it could happen that
X    isdn4linux rejects an incoming call, which belongs to another device on
-   the bus. 
+   the bus.
X 
X    "isdnctrl addslave <InterfaceName> <SlaveName>
X    Creates a slave interface for channel-bundling. Slave interfaces are
@@ -539,9 +559,9 @@
X    isdnctrl eaz isdn1 4      # listen on 12345674(1tr6) only.
X    ...
X    isdnctrl eaz isdn2 987654 # listen on 987654(euro) only.
-   
+
X    Same scheme is used with AT&E...  at the tty's.
-  
+
X 6. If you want to write a new low-level-driver, you are welcome.
X    The interface to the link-level-module is described in the file INTERFACE.
X    If the interface should be expanded for any reason, don't do it
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax
--- v2.3.3/linux/Documentation/isdn/README.HiSax	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/isdn/README.HiSax	Sun May 23 10:03:41 1999
@@ -1,7 +1,7 @@
X HiSax is a Linux hardware-level driver for passive ISDN cards with Siemens
X chipset (ISAC_S 2085/2086/2186, HSCX SAB 82525). It is based on the Teles
X driver from Jan den Ouden.
-It is meant to be used with isdn4linux, an ISDN link-level module for Linux 
+It is meant to be used with isdn4linux, an ISDN link-level module for Linux
X written by Fritz Elfert.
X 
X     This program is free software; you can redistribute it and/or modify
@@ -25,24 +25,33 @@
X Teles 8.0/16.0/16.3 and compatible ones
X Teles 16.3c
X Teles S0/PCMCIA
-Creatix PnP S0 
+Teles PCI
+Teles S0Box
+Creatix S0Box
+Creatix PnP S0
X Compaq ISDN S0 ISA card
X AVM A1 (Fritz, Teledat 150)
+AVM Fritz PCMCIA
+AVM Fritz PnP
+AVM Fritz PCI
X ELSA Microlink PCC-16, PCF, PCF-Pro, PCC-8
X ELSA Quickstep 1000
X ELSA Quickstep 1000PCI
X ELSA Quickstep 3000 (same settings as QS1000)
+ELSA Quickstep 3000PCI
X ELSA PCMCIA
X ITK ix1-micro Rev.2
X Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
X Eicon.Diehl Diva Piccola
X ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
X Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
+PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink)
X HFC-2BS0 based cards (TeleInt SA1)
-Sedlbauer Speed Card (Speed Win, Teledat 100)
-Sedlbauer Speed Star (PCMCIA)
+Sedlbauer Speed Card (Speed Win, Teledat 100, PCI, Fax+)
+Sedlbauer Speed Star/Speed Star2 (PCMCIA)
+Sedlbauer ISDN-Controller PC/104
X USR Sportster internal TA (compatible Stollmann tina-pp V3)
-ith Kommunikationstechnik GmbH MIC 16 ISA card 
+ith Kommunikationstechnik GmbH MIC 16 ISA card
X Traverse Technologie NETjet PCI S0 card
X Dr. Neuhaus Niccy PnP/PCI
X 
@@ -50,6 +59,8 @@
X       PCC-8: not tested yet
X       Teles PCMCIA is EXPERIMENTAL
X       Teles 16.3c is EXPERIMENTAL
+      Teles PCI is EXPERIMENTAL
+      Teles S0Box is EXPERIMENTAL
X       Eicon.Diehl Diva U interface not tested
X 
X If you know other passive cards with the Siemens chipset, please let me know.
@@ -113,7 +124,7 @@
X correct one during kernel config. Valid values are "1" for German 1TR6,
X "2" for EDSS1 (Euro ISDN) and "3" for leased lines (no D-Channel).
X 
-The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying 
+The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying
X the I/O addresses of the ISAC and HSCX chips, respectively.
X 
X Card types:
@@ -135,24 +146,29 @@
X    11   Eicon.Diehl Diva ISA PnP irq, io
X    11   Eicon.Diehl Diva PCI     no parameter
X    12   ASUS COM ISDNLink        irq, io  (from isapnp setup)
-   13   HFC-2BS0 based cards     irq, io  
+   13   HFC-2BS0 based cards     irq, io
X    14   Teles 16.3c PnP          irq, io
-   15   Sedlbauer Speed Card     irq, io  
-   16   USR Sportster internal   irq, io  
-   17   MIC card                 irq, io  
+   15   Sedlbauer Speed Card     irq, io
+   15   Sedlbauer PC/104         irq, io
+   15   Sedlbauer Speed PCI	 no parameter
+   16   USR Sportster internal   irq, io
+   17   MIC card                 irq, io
X    18   ELSA Quickstep 1000PCI   no parameter
X    19   Compaq ISDN S0 ISA card  irq, io0, io1, io (from isapnp setup io=IO2)
X    20   NETjet PCI card          no parameter
+   21   Teles PCI                no parameter
X    22   Sedlbauer Speed Star (PCMCIA) irq, io (set with card manager)
X    24   Dr. Neuhaus Niccy PnP    irq, io0, io1 (from isapnp setup)
X    24   Dr. Neuhaus Niccy PCI    no parameter
+   25   Teles S0Box              irq, io (of the used lpt port)
+   26   AVM A1 PCMCIA (Fritz!)   irq, io (set with card manager)
+   27   AVM PnP (Fritz!PnP)      irq, io  (from isapnp setup)
+   27   AVM PCI (Fritz!PCI)      no parameter
+   28   Sedlbauer Speed Fax+     irq, io (from isapnp setup)
X 
X 
-        
-At the moment IRQ sharing is not possible. Please make sure that your IRQ
-is free and enabled for ISA use.
-Note: For using the ELSA PCMCIA you need the cardmanager under MSDOS for
-enabling at the moment, then boot linux with loadlin.
+At the moment IRQ sharing is only possible with PCI cards. Please make sure
+that your IRQ is free and enabled for ISA use.
X 
X 
X Examples for module loading
@@ -169,7 +185,7 @@
X 4. Any ELSA PCC/PCF card, Euro ISDN
X    modprobe hisax type=6 protocol=2
X 
-5. Teles 16.3 PnP, Euro ISDN, with isapnp configured 
+5. Teles 16.3 PnP, Euro ISDN, with isapnp configured
X    isapnp config:  (INT 0 (IRQ 10 (MODE +E)))
X  		   (IO 0 (BASE 0x0580))
X                    (IO 1 (BASE 0x0180))
@@ -210,8 +226,8 @@
X                 Note: the ID string must start with an alphabetical character!
X 
X Card types:
-       
-  type  
+
+type
X     1 	Teles 16.0     	        pa=irq  pb=membase  pc=iobase
X     2 	Teles  8.0              pa=irq  pb=membase
X     3 	Teles 16.3              pa=irq  pb=iobase
@@ -227,22 +243,33 @@
X    12   ASUS COM ISDNLink       ONLY WORKS AS A MODULE !
X    13	HFC-2BS0 based cards    pa=irq  pb=io
X    14   Teles 16.3c PnP         ONLY WORKS AS A MODULE !
-   15	Sedlbauer Speed Card    pa=irq  pb=io (Speed Win only as module !)  
+   15	Sedlbauer Speed Card    pa=irq  pb=io (Speed Win only as module !)
+   15   Sedlbauer PC/104        pa=irq  pb=io
+   15   Sedlbauer Speed PCI	no parameter
X    16   USR Sportster internal  pa=irq  pb=io
X    17   MIC card                pa=irq  pb=io
X    18   ELSA Quickstep 1000PCI  no parameter
X    19   Compaq ISDN S0 ISA card ONLY WORKS AS A MODULE !
X    20   NETjet PCI card         no parameter
-   21   Sedlbauer Speed Star (PCMCIA)  pa=irq, pb=io  (set with card manager)
+   21   Teles PCI               no parameter
+   22   Sedlbauer Speed Star (PCMCIA)  pa=irq, pb=io  (set with card manager)
+   24   Dr. Neuhaus Niccy PnP   ONLY WORKS AS A MODULE !
+   24   Dr. Neuhaus Niccy PCI   no parameter
+   25   Teles S0Box             irq, io (of the used lpt port)
+   26   AVM A1 PCMCIA (Fritz!)  irq, io (set with card manager)
+   27   AVM PnP (Fritz!PnP)     ONLY WORKS AS A MODULE !
+   27   AVM PCI (Fritz!PCI)     no parameter
+   28   Sedlbauer Speed Fax+    ONLY WORKS AS A MODULE !
+
X 
X Running the driver
X ------------------
X 
-When you insmod isdn.o and hisax.o (or with the in-kernel version, during 
+When you insmod isdn.o and hisax.o (or with the in-kernel version, during
X boot time), a few lines should appear in your syslog. Look for something like:
X 
X Apr 13 21:01:59 kke01 kernel: HiSax: Driver for Siemens chip set ISDN cards
-Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.1
+Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.9
X Apr 13 21:01:59 kke01 kernel: HiSax: Revisions 1.14/1.9/1.10/1.25/1.8
X Apr 13 21:01:59 kke01 kernel: HiSax: Total 1 card defined
X Apr 13 21:01:59 kke01 kernel: HiSax: Card 1 Protocol EDSS1 Id=HiSax1 (0)
@@ -257,7 +284,7 @@
X Apr 13 21:01:59 kke01 kernel: HiSax: 2 channels added
X 
X This means that the card is ready for use.
-Cabling problems or line-downs are not detected, and only some ELSA cards can 
+Cabling problems or line-downs are not detected, and only some ELSA cards can
X detect the S0 power.
X 
X Remember that, according to the new strategy for accessing low-level drivers
@@ -265,8 +292,7 @@
X insmod: Simply append hisax_id=<SomeString> to the insmod command line. This
X string MUST NOT start with a digit or a small 'x'!
X 
-At this point you can run a 'cat /dev/isdnctrl0' and view debugging 
-messages. 
+At this point you can run a 'cat /dev/isdnctrl0' and view debugging messages.
X 
X At the moment, debugging messages are enabled with the hisaxctrl tool:
X 
@@ -283,28 +309,35 @@
X 
X With DebugCmd set to 1:
X 
-         1  Link-level <--> hardware-level communication
-         2  Top state machine
-         4  D-Channel Q.931 (call control messages)
-         8  D-Channel Q.921
-        16  B-Channel X.75
-        32  D-Channel l2
-        64  B-Channel l2
-       128  D-Channel link state debugging
-       256  B-Channel link state debugging
-       512  TEI debug
-      1024  LOCK debug in callc.c
-      2048  More paranoid debug in callc.c (not for normal use)
+   0x0001  Link-level <--> hardware-level communication
+   0x0002  Top state machine
+   0x0004  D-Channel Frames for isdnlog
+   0x0008  D-Channel Q.921
+   0x0010  B-Channel X.75
+   0x0020  D-Channel l2
+   0x0040  B-Channel l2
+   0x0080  D-Channel link state debugging
+   0x0100  B-Channel link state debugging
+   0x0200  TEI debug
+   0x0400  LOCK debug in callc.c
+   0x0800  More paranoid debug in callc.c (not for normal use)
+   0x1000  D-Channel l1 state debugging
+   0x2000  B-Channel l1 state debugging
X 
X With DebugCmd set to 11:
X 
-         1  Warnings (default: on)
-         2  IRQ status
-         4  ISAC
-         8  ISAC FIFO
-        16  HSCX
-        32  HSCX FIFO (attention: full B-Channel output!)
-        64  D-Channel LAPD frame types
+   0x0001  Warnings (default: on)
+   0x0002  IRQ status
+   0x0004  ISAC
+   0x0008  ISAC FIFO
+   0x0010  HSCX
+   0x0020  HSCX FIFO (attention: full B-Channel output!)
+   0x0040  D-Channel LAPD frame types
+   0x0080  IPAC debug
+   0x0100  HFC receive debug
+   0x0200  ISAC monitor debug
+   0x0400  D-Channel frames for isdnlog (set with 1 0x4 too)
+   0x0800  D-Channel message verbose
X 
X With DebugCmd set to 13:
X 
@@ -317,27 +350,39 @@
X 
X Because of some obscure problems with some switch equipment, the delay
X between the CONNECT message and sending the first data on the B-channel is now
-configurable with 
+configurable with
X 
X hisaxctrl <DriverId> 2 <delay>
X <delay> in ms Value between 50 and 800 ms is recommended.
X 
+Downloading Firmware
+--------------------
+At the moment, the Sedlbauer speed fax+ is the only card, which
+needs to download firmware.
+The firmware is downloaded with the hisaxctrl tool:
+
+    hisaxctrl <DriverId> 9 <firmware_filename>
+
+<DriverId> default is HiSax, if you didn't specify one,
+
+where <firmware_filename> is the filename of the firmware file.
+
+For example, 'hisaxctrl HiSax 9 ISAR.BIN' downloads the firmware for
+ISAR based cards (like the Sedlbauer speed fax+).
X 
X Warning
X -------
-HiSax is a work in progress and may crash your machine. It has not been
-certified and therefore operation on your PTT's ISDN network is probably
-illegal.
-
+HiSax is a work in progress and may crash your machine.
+For certification look at HiSax.cert file.
X 
X Limitations
X -----------
X At this time, HiSax only works on Euro ISDN lines and German 1TR6 lines.
-For leased lines see appendix. 
+For leased lines see appendix.
X 
-Bugs 
+Bugs
X ----
-If you find any, please let me know. 
+If you find any, please let me know.
X 
X 
X Thanks
@@ -354,8 +399,10 @@
X 	Stephan von Krawczynski
X 	Juergen Quade for the Leased Line part
X 	Klaus Lichtenwalder (Klaus.Lic...@WebForum.DE), for ELSA PCMCIA support
+	Enrik Berkhan (en...@starfleet.inka.de) for S0BOX specific stuff
+	Ton van Rosmalen for Teles PCI
X         and more people who are hunting bugs. (If I forgot somebody, please
-	send me a mail). 
+	send me a mail).
X 
X         Firma ELSA GmbH
X         Firma Eicon.Diehl GmbH
@@ -364,20 +411,23 @@
X 	Firma S.u.S.E
X 	Firma ith Kommunikationstechnik GmbH
X 	Firma Traverse Technologie Australia
-        
+	Firma Medusa GmbH  (www.medusa.de).
+	Firma Quant-X Austria for sponsoring a DEC Alpha board+CPU
+	Firma Cologne Chip Designs GmbH
+
X         My girl friend and partner in life Ute for her patience with me.
X 
X 
X Enjoy,
X 
-Karsten Keil   
-ke...@temic-ech.spacenet.de
+Karsten Keil
+ke...@isdn4linux.de
X 
X 
X Appendix: Teles PCMCIA driver
X -----------------------------
X 
-See 
+See
X    http://www.stud.uni-wuppertal.de/~ea0141/pcmcia.html
X for instructions.
X 
@@ -451,7 +501,7 @@
X       /sbin/isdnctrl l2_prot isdn0 hdlc
X       # Attention you must not set an outgoing number !!! This won't work !!!
X       # The incomming number is LEASED0 for the first card, LEASED1 for the
-      # second and so on. 
+      # second and so on.
X       /sbin/isdnctrl addphone isdn0 in LEASED0
X       # Here is no need to bind the channel.
X    c) in case the remote partner is a CISCO:
@@ -461,11 +511,12 @@
X    e) set the routes
X       /sbin/route add -host ${REMOTE_IP} isdn0
X       /sbin/route add default gw ${REMOTE_IP}
-   f) switch the card into leased mode for each used B-channel 
+   f) switch the card into leased mode for each used B-channel
X       /sbin/hisaxctrl HiSax 5 1
- 
+
X Remarks:
X a) If you have a CISCO don't forget to switch off the KEEP ALIVE option!
+b) Use state of the art isdn4k-utils
X 
X Here an example script:
X #!/bin/sh
@@ -517,6 +568,7 @@
X 			/sbin/isdnctrl encap isdn0s cisco-h
X 		fi
X 	fi
+	/sbin/isdnctrl dialmode isdn0 auto
X 	# configure tcp/ip
X 	/sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP}
X 	/sbin/route add -host ${REMOTE_IP} isdn0
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.act2000 linux/Documentation/isdn/README.act2000
--- v2.3.3/linux/Documentation/isdn/README.act2000	Thu Jan  7 08:41:54 1999
+++ linux/Documentation/isdn/README.act2000	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-$Id: README.act2000,v 1.1 1997/09/24 23:50:16 fritz Exp $
+$Id: README.act2000,v 1.2 1998/04/29 19:49:06 he Exp $
X 
X This document describes the ACT2000 driver for the
X IBM Active 2000 ISDN card.
@@ -7,7 +7,7 @@
X Version. Currently, only the ISA-Bus version of the card is supported.
X However MCA and PCMCIA will follow soon.
X 
-The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
+The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set
X manually using the DIP switches.
X 
X Setting up the DIP switches for the IBM Active 2000 ISDN card:
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.audio linux/Documentation/isdn/README.audio
--- v2.3.3/linux/Documentation/isdn/README.audio	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/isdn/README.audio	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-$Id: README.audio,v 1.5 1997/02/23 23:53:46 fritz Exp $
+$Id: README.audio,v 1.7 1998/07/26 18:45:34 armin Exp $
X 
X ISDN subsystem for Linux.
X   Description of audio mode.
@@ -50,10 +50,11 @@
X                          the application. See below for data format
X 
X         AT+VSD=x,y       Set silence-detection parameters.
-                         NO EFFECT, supported for compatibility
-                         only. Possible parameters:
-                           x = 0 ... 31
-                           y = 0 ... 255
+                         Possible parameters:
+                           x = 0 ... 31  sensitivity threshold level.
+                                         (default 0 , deactivated)
+                           y = 0 ... 255 range of interval in units
+                                         of 0.1 second. (default 70)
X         AT+VSD=?         Report possible parameters.
X         AT+VSD?          Show current parameters.
X 
@@ -102,13 +103,14 @@
X     <DLE>C                  Touchtone "C" received.
X     <DLE>D                  Touchtone "D" received.
X 
+    <DLE>q                  quiet. Silence detected after non-silence.
+    <DLE>s                  silence. Silence detected from the
+                            start of recording.
+
X     Currently unsupported DLE sequences:
X 
X     <DLE>c                  FAX calling tone received.
X     <DLE>b                  busy tone received.
-    <DLE>q                  quiet. Silence detected after non-silence.
-    <DLE>s                  silence. Silence detected from the
-                            start of recording.
X 
X   Audio playback.
X 
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.concap linux/Documentation/isdn/README.concap
--- v2.3.3/linux/Documentation/isdn/README.concap	Thu Jan  7 08:41:54 1999
+++ linux/Documentation/isdn/README.concap	Sun May 23 10:03:41 1999
@@ -256,3 +256,4 @@
X of the concap interface when a trivial concap protocol is used.
X Nevertheless, the device remains able to support encapsulation
X protocol configuration.
+
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.eicon linux/Documentation/isdn/README.eicon
--- v2.3.3/linux/Documentation/isdn/README.eicon	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/README.eicon	Sun May 23 10:03:41 1999
@@ -0,0 +1,92 @@
+$Id: README.eicon,v 1.3 1999/03/29 11:10:04 armin Exp $
+
+(c) 1999 Cytronics & Melware
+
+This document describes the eicon driver for the
+Eicon.Diehl active ISDN cards.
+
+It is meant to be used with isdn4linux, an ISDN link-level module for Linux.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+NOTE : Since the eicon driver is still experimental, this README file
+       may be incomplete and not up to date.
+
+
+However, the driver should work under following conditions :
+
+Supported Cards
+---------------
+
+- S-Card ISA
+- SX-Card ISA
+- SXn-Card ISA
+- SCOM-Card ISA
+- Quadro-Card ISA
+- S2M-Card ISA
+- DIVA Server BRI/PCI 2M
+- DIVA Server PRI/PCI 2M (9M 23M 30M)
+  (Only analog modem functions of the DSPs are currently implemented)
+
+ISDN D-Channel Protocols
+------------------------
+
+- ETSI (Euro-DSS1) 
+- 1TR6 (German ISDN) *not testet*
+
+
+
+You can load the module simply by using the insmod or modprobe function :
+
+  insmod eicon [id=driverid] [membase=<membase>] [irq=<irq>]
+
+
+The module will automatically probe the PCI-cards. If the id-options
+is omitted, the driver will assume 'eicon0' for the first pci card and
+increases the digit with each further card. With a given driver-id
+the module appends a number starting with '0'.
+
+For ISA-cards you have to specify membase, irq and id. If id or
+membase is missing/invalid, the driver will not be loaded except
+PCI-cards were found. Additional ISA-cards and irq/membase changes
+can be done with the eiconctrl utility.
+
+After loading the module, you have to download the protocol and
+dsp-code by using the eiconctrl utility of isdn4k-utils.
+
+
+Example for loading and starting a BRI card with E-DSS1 Protocol.
+
+	eiconctrl [-d DriverId] load etsi
+
+
+Example for loading and starting a PRI card with E-DSS1 Protocol.
+
+	eiconctrl [-d DriverId] load etsi -s2 -n
+
+
+Details about using the eiconctrl utility are in 'man eiconctrl'
+or will be printed by starting eiconctrl without any parameters.
+
+
+
+Any reports about bugs, errors and even wishes are welcome.
+
+
+Have fun !
+
+Armin Schindler
+m...@melware.de
+http://www.melware.de
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.icn linux/Documentation/isdn/README.icn
--- v2.3.3/linux/Documentation/isdn/README.icn	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/isdn/README.icn	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-$Id: README.icn,v 1.5 1997/04/23 18:55:55 fritz Exp $
+$Id: README.icn,v 1.6 1998/04/29 19:49:08 he Exp $
X 
X You can get the ICN-ISDN-card from:
X 
diff -u --recursive --new-file v2.3.3/linux/Documentation/isdn/README.x25 linux/Documentation/isdn/README.x25
--- v2.3.3/linux/Documentation/isdn/README.x25	Thu Jan  7 08:41:54 1999
+++ linux/Documentation/isdn/README.x25	Sun May 23 10:03:41 1999
@@ -1,29 +1,24 @@
- 
-X25 support within isdn4linux
-
-
-This is experimental code and should be used with linux version 2.1.72.
-or later. Use it completely at your own risk.
-
+  
+X.25 support within isdn4linux
+==============================
X 
+This is alpha/beta test code. Use it completely at your own risk.
X As new versions appear, the stuff described here might suddenly change
X or become invalid without notice.
X 
X Keep in mind:
X 
-You are using an experimental kernel (2.1.x series) with an experimental
-x25 protocol implementation and experimental x25-on-top-of-isdn extensions.
-Thus, be prepared to face problems related therefrom.
+You are using several new parts of the 2.2.x kernel series which
+have not been tested in a large scale. Therefore, you might encounter
+more bugs as usual.
X 
-- If you connect to an x25 neighbour not operated by yourself, ASK the
+- If you connect to an X.25 neighbour not operated by yourself, ASK the
X   other side first. Be prepared that bugs in the protocol implementation
-  might result in problems (even crashing the peer, however such ugly events
-  should only happen if your peer's protocol implementation has serious bugs).
+  might result in problems.
X 
X - This implementation has never wiped out my whole hard disk yet. But as
-  this is experimental code, don't blame me if that happened to you. Take
-  appropriate actions (such as backing up important data) before
-  trying this code.
+  this is experimental code, don't blame me if that happened to you.
+  Backing up important data will never harm.
X 
X - Monitor your isdn connections while using this software. This should
X   prevent you from undesired phone bills in case of driver problems.
@@ -32,7 +27,7 @@
X 
X 
X How to configure the kernel
-
+===========================
X  
X The ITU-T (former CCITT) X.25 network protocol layer has been implemented
X in the Linux source tree since version 2.1.16. The isdn subsystem might be 
@@ -48,32 +43,33 @@
X compilation. You currently also need to enable
X "Prompt for development and/or incomplete code/drivers" from the
X "Code maturity level options" menu. For the x25trace utility to work
-you also need to enable "Packet socket" (I recommend to choose "y",
-not "m" for testing) from the networking options.
+you also need to enable "Packet socket".
X 
+For local testing it is also recommended to enable the isdnloop driver
+from the isdn subsystem's configuration menu.
X 
-For testing you should also select the isdnloop driver from the
-isdn subsystem's configuration menu.
+For testing, it is recommended that all isdn drivers and the X.25 PLP
+protocol are compiled as loadable modules. Like this, you can recover
+from certain errors by simply unloading and reloading the modules.
X 
X 
X 
X What's it for? How to use it?
+=============================
X 
-
-X25 on top of isdn might be useful with two different scenarios:
+X.25 on top of isdn might be useful with two different scenarios:
X 
X - You might want to access a public X.25 data network from your Linux box.
X   You can use i4l if you were physically connected to the X.25 switch
-  by an ISDN line (leased line as well as dial up connection should work,
-  but connecting to x.25 network switches is currently untested. Testing
-  needs to be done by somebody with access to such a switch.) 
-
-- Or you might want to operate certain ISDN teleservices on 
-  your linux box. A lot of those teleservices run on top of the ISO-8208 
-  network layer protocol. ISO-8208 is essentially the same as ITU-T X.25.
+  by an ISDN line (leased line as well as dial up connection should work)
+
+- Or you might want to operate certain ISDN teleservices on your linux
+  box. A lot of those teleservices run on top of the ISO-8208
+  (DTE-DTE mode) network layer protocol. ISO-8208 is essentially the
+  same as ITU-T X.25.
X 
-  Popular candidates of such teleservices are EUROFILE transfer or any
-  teleservice applying ITU-T recommendation T.90 (i.e., AFAIK, G4 Fax).
+  Popular candidates of such teleservices are EUROfile transfer or any
+  teleservice applying ITU-T recommendation T.90.
X 
X To use the X.25 protocol on top of isdn, just create an isdn network
X interface as usual, configure your own and/or peer's ISDN numbers,
@@ -81,21 +77,18 @@
X 
X    isdnctrl encap <iface-name> x25iface.
X 
-Once encap is set like this, the device can be used by the x25 packet layer.
+Once encap is set like this, the device can be used by the X.25 packet layer.
X 
-All the stuff needed for x25 is implemented inside the isdn link
+All the stuff needed for X.25 is implemented inside the isdn link
X level (mainly isdn_net.c and some new source files). Thus, it should
-work with every existing HL driver. I was able to successfully open x25
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 01'
echo 'File patch-2.3.4 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 08 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 08; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
X 
X #if _FP_W_TYPE_SIZE < 32
X #error "Here's a nickel kid.  Go buy yourself a real computer."
@@ -49,7 +69,13 @@
X 
X #define FP_DECL_D(X)		_FP_DECL(2,X)
X #define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_2(D,X,val)
+#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_2_P(D,X,val)
X #define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_2(D,val,X)
+#define FP_PACK_RAW_DP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_2_P(D,val,X);	\
+  } while (0)
X 
X #define FP_UNPACK_D(X,val)		\
X   do {					\
@@ -57,24 +83,42 @@
X     _FP_UNPACK_CANONICAL(D,2,X);	\
X   } while (0)
X 
+#define FP_UNPACK_DP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_2_P(D,X,val);	\
+    _FP_UNPACK_CANONICAL(D,2,X);	\
+  } while (0)
+
X #define FP_PACK_D(val,X)		\
X   do {					\
X     _FP_PACK_CANONICAL(D,2,X);		\
X     _FP_PACK_RAW_2(D,val,X);		\
X   } while (0)
X 
-#define FP_NEG_D(R,X)		_FP_NEG(D,2,R,X)
-#define FP_ADD_D(R,X,Y)		_FP_ADD(D,2,R,X,Y)
-#define FP_SUB_D(R,X,Y)		_FP_SUB(D,2,R,X,Y)
-#define FP_MUL_D(R,X,Y)		_FP_MUL(D,2,R,X,Y)
-#define FP_DIV_D(R,X,Y)		_FP_DIV(D,2,R,X,Y)
-#define FP_SQRT_D(R,X)		_FP_SQRT(D,2,R,X)
+#define FP_PACK_DP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,2,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_2_P(D,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,2,X)
+#define FP_NEG_D(R,X)			_FP_NEG(D,2,R,X)
+#define FP_ADD_D(R,X,Y)			_FP_ADD(D,2,R,X,Y)
+#define FP_SUB_D(R,X,Y)			_FP_SUB(D,2,R,X,Y)
+#define FP_MUL_D(R,X,Y)			_FP_MUL(D,2,R,X,Y)
+#define FP_DIV_D(R,X,Y)			_FP_DIV(D,2,R,X,Y)
+#define FP_SQRT_D(R,X)			_FP_SQRT(D,2,R,X)
+#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_2(R,S,T,X,Q)
X 
X #define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,2,r,X,Y,un)
X #define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,2,r,X,Y)
X 
-#define FP_TO_INT_D(r,X,rsz,rsg)  _FP_TO_INT(D,2,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt)  _FP_FROM_INT(D,2,X,r,rs,rt)
+#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,2,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_2(X)
+#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_2(X)
X 
X #else
X 
@@ -96,7 +140,13 @@
X 
X #define FP_DECL_D(X)		_FP_DECL(1,X)
X #define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_1(D,X,val)
+#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_1_P(D,X,val)
X #define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_1(D,val,X)
+#define FP_PACK_RAW_DP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_1_P(D,val,X);	\
+  } while (0)
X 
X #define FP_UNPACK_D(X,val)		\
X   do {					\
@@ -104,18 +154,33 @@
X     _FP_UNPACK_CANONICAL(D,1,X);	\
X   } while (0)
X 
+#define FP_UNPACK_DP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1_P(D,X,val);	\
+    _FP_UNPACK_CANONICAL(D,1,X);	\
+  } while (0)
+
X #define FP_PACK_D(val,X)		\
X   do {					\
X     _FP_PACK_CANONICAL(D,1,X);		\
X     _FP_PACK_RAW_1(D,val,X);		\
X   } while (0)
X 
-#define FP_NEG_D(R,X)		_FP_NEG(D,1,R,X)
-#define FP_ADD_D(R,X,Y)		_FP_ADD(D,1,R,X,Y)
-#define FP_SUB_D(R,X,Y)		_FP_SUB(D,1,R,X,Y)
-#define FP_MUL_D(R,X,Y)		_FP_MUL(D,1,R,X,Y)
-#define FP_DIV_D(R,X,Y)		_FP_DIV(D,1,R,X,Y)
-#define FP_SQRT_D(R,X)		_FP_SQRT(D,1,R,X)
+#define FP_PACK_DP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,1,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_1_P(D,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,1,X)
+#define FP_NEG_D(R,X)			_FP_NEG(D,1,R,X)
+#define FP_ADD_D(R,X,Y)			_FP_ADD(D,1,R,X,Y)
+#define FP_SUB_D(R,X,Y)			_FP_SUB(D,1,R,X,Y)
+#define FP_MUL_D(R,X,Y)			_FP_MUL(D,1,R,X,Y)
+#define FP_DIV_D(R,X,Y)			_FP_DIV(D,1,R,X,Y)
+#define FP_SQRT_D(R,X)			_FP_SQRT(D,1,R,X)
+#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)
X 
X /* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
X    the target machine.  */
@@ -123,7 +188,10 @@
X #define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,1,r,X,Y,un)
X #define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,1,r,X,Y)
X 
-#define FP_TO_INT_D(r,X,rsz,rsg)  _FP_TO_INT(D,1,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt)  _FP_FROM_INT(D,1,X,r,rs,rt)
+#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,1,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,1,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_1(X)
+#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_1(X)
X 
X #endif /* W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/extended.h linux/arch/sparc64/math-emu/extended.h
--- v2.3.3/linux/arch/sparc64/math-emu/extended.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/math-emu/extended.h	Sat May 29 11:09:04 1999
@@ -0,0 +1,388 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Extended Precision.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek (j...@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel, kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_E         (4*_FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_E		(2*_FP_W_TYPE_SIZE)
+#endif
+
+#define _FP_FRACBITS_E		64
+#define _FP_FRACXBITS_E		(_FP_FRACTBITS_E - _FP_FRACBITS_E)
+#define _FP_WFRACBITS_E		(_FP_WORKBITS + _FP_FRACBITS_E)
+#define _FP_WFRACXBITS_E	(_FP_FRACTBITS_E - _FP_WFRACBITS_E)
+#define _FP_EXPBITS_E		15
+#define _FP_EXPBIAS_E		16383
+#define _FP_EXPMAX_E		32767
+
+#define _FP_QNANBIT_E		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_E		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_E		\
+	((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_E
+{
+   long double flt;
+   struct 
+   {
+#if __BYTE_ORDER == __BIG_ENDIAN
+      unsigned long pad1 : _FP_W_TYPE_SIZE;
+      unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+      unsigned long sign : 1;
+      unsigned long exp : _FP_EXPBITS_E;
+      unsigned long frac1 : _FP_W_TYPE_SIZE;
+      unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+      unsigned long frac0 : _FP_W_TYPE_SIZE;
+      unsigned long frac1 : _FP_W_TYPE_SIZE;
+      unsigned exp : _FP_EXPBITS_E;
+      unsigned sign : 1;
+#endif /* not bigendian */
+   } bits __attribute__((packed));
+};
+
+
+#define FP_DECL_E(X)		_FP_DECL(4,X)
+
+#define FP_UNPACK_RAW_E(X, val)				\
+  do {							\
+    union _FP_UNION_E _flo; _flo.flt = (val);		\
+							\
+    X##_f[2] = 0; X##_f[3] = 0;				\
+    X##_f[0] = _flo.bits.frac0;				\
+    X##_f[1] = _flo.bits.frac1;				\
+    X##_e  = _flo.bits.exp;				\
+    X##_s  = _flo.bits.sign;				\
+    if (!X##_e && (X##_f[1] || X##_f[0])		\
+        && !(X##_f[1] & _FP_IMPLBIT_E))			\
+      {							\
+        X##_e++;					\
+        FP_SET_EXCEPTION(FP_EX_DENORM);			\
+      }							\
+  } while (0)
+
+#define FP_UNPACK_RAW_EP(X, val)			\
+  do {							\
+    union _FP_UNION_E *_flo =				\
+    (union _FP_UNION_E *)(val);				\
+							\
+    X##_f[2] = 0; X##_f[3] = 0;				\
+    X##_f[0] = _flo->bits.frac0;			\
+    X##_f[1] = _flo->bits.frac1;			\
+    X##_e  = _flo->bits.exp;				\
+    X##_s  = _flo->bits.sign;				\
+    if (!X##_e && (X##_f[1] || X##_f[0])		\
+        && !(X##_f[1] & _FP_IMPLBIT_E))			\
+      {							\
+        X##_e++;					\
+        FP_SET_EXCEPTION(FP_EX_DENORM);			\
+      }							\
+  } while (0)
+
+#define FP_PACK_RAW_E(val, X)				\
+  do {							\
+    union _FP_UNION_E _flo;				\
+							\
+    if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;		\
+    else X##_f[1] &= ~(_FP_IMPLBIT_E);			\
+    _flo.bits.frac0 = X##_f[0];				\
+    _flo.bits.frac1 = X##_f[1];				\
+    _flo.bits.exp   = X##_e;				\
+    _flo.bits.sign  = X##_s;				\
+							\
+    (val) = _flo.flt;					\
+  } while (0)
+
+#define FP_PACK_RAW_EP(val, X)				\
+  do {							\
+    if (!FP_INHIBIT_RESULTS)				\
+      {							\
+	union _FP_UNION_E *_flo =			\
+	  (union _FP_UNION_E *)(val);			\
+							\
+	if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;		\
+	else X##_f[1] &= ~(_FP_IMPLBIT_E);		\
+	_flo->bits.frac0 = X##_f[0];			\
+	_flo->bits.frac1 = X##_f[1];			\
+	_flo->bits.exp   = X##_e;			\
+	_flo->bits.sign  = X##_s;			\
+      }							\
+  } while (0)
+
+#define FP_UNPACK_E(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_E(X,val);		\
+    _FP_UNPACK_CANONICAL(E,4,X);	\
+  } while (0)
+
+#define FP_UNPACK_EP(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_2_P(X,val);		\
+    _FP_UNPACK_CANONICAL(E,4,X);	\
+  } while (0)
+
+#define FP_PACK_E(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,4,X);		\
+    FP_PACK_RAW_E(val,X);		\
+  } while (0)
+
+#define FP_PACK_EP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,4,X);		\
+    FP_PACK_RAW_EP(val,X);		\
+  } while (0)
+
+#define FP_ISSIGNAN_E(X)	_FP_ISSIGNAN(E,4,X)
+#define FP_NEG_E(R,X)		_FP_NEG(E,4,R,X)
+#define FP_ADD_E(R,X,Y)		_FP_ADD(E,4,R,X,Y)
+#define FP_SUB_E(R,X,Y)		_FP_SUB(E,4,R,X,Y)
+#define FP_MUL_E(R,X,Y)		_FP_MUL(E,4,R,X,Y)
+#define FP_DIV_E(R,X,Y)		_FP_DIV(E,4,R,X,Y)
+#define FP_SQRT_E(R,X)		_FP_SQRT(E,4,R,X)
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ * This has special _E version because standard _4 square
+ * root would not work (it has to start normally with the
+ * second word and not the first), but as we have to do it
+ * anyway, we optimize it by doing most of the calculations
+ * in two UWtype registers instead of four.
+ */
+ 
+#define _FP_SQRT_MEAT_E(R, S, T, X, q)			\
+  do {							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    _FP_FRAC_SRL_4(X, (_FP_WORKBITS));			\
+    while (q)						\
+      {							\
+	T##_f[1] = S##_f[1] + q;			\
+	if (T##_f[1] <= X##_f[1])			\
+	  {						\
+	    S##_f[1] = T##_f[1] + q;			\
+	    X##_f[1] -= T##_f[1];			\
+	    R##_f[1] += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    while (q)						\
+      {							\
+	T##_f[0] = S##_f[0] + q;			\
+	T##_f[1] = S##_f[1];				\
+	if (T##_f[1] < X##_f[1] || 			\
+	    (T##_f[1] == X##_f[1] &&			\
+	     T##_f[0] <= X##_f[0]))			\
+	  {						\
+	    S##_f[0] = T##_f[0] + q;			\
+	    S##_f[1] += (T##_f[0] > S##_f[0]);		\
+	    _FP_FRAC_DEC_2(X, T);			\
+	    R##_f[0] += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    _FP_FRAC_SLL_4(R, (_FP_WORKBITS));			\
+    if (X##_f[0] | X##_f[1])				\
+      {							\
+	if (S##_f[1] < X##_f[1] || 			\
+	    (S##_f[1] == X##_f[1] &&			\
+	     S##_f[0] < X##_f[0]))			\
+	  R##_f[0] |= _FP_WORK_ROUND;			\
+	R##_f[0] |= _FP_WORK_STICKY;			\
+      }							\
+  } while (0)
+
+#define FP_CMP_E(r,X,Y,un)	_FP_CMP(E,4,r,X,Y,un)
+#define FP_CMP_EQ_E(r,X,Y)	_FP_CMP_EQ(E,4,r,X,Y)
+
+#define FP_TO_INT_E(r,X,rsz,rsg)	_FP_TO_INT(E,4,r,X,rsz,rsg)
+#define FP_FROM_INT_E(X,r,rs,rt)	_FP_FROM_INT(E,4,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_E(X)	(X##_f[2])
+#define _FP_FRAC_HIGH_RAW_E(X)	(X##_f[1])
+
+#else   /* not _FP_W_TYPE_SIZE < 64 */
+union _FP_UNION_E
+{
+  long double flt /* __attribute__((mode(TF))) */ ;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+    unsigned sign  : 1;
+    unsigned exp   : _FP_EXPBITS_E;
+    unsigned long frac : _FP_W_TYPE_SIZE;
+#else
+    unsigned long frac : _FP_W_TYPE_SIZE;
+    unsigned exp   : _FP_EXPBITS_E;
+    unsigned sign  : 1;
+#endif
+  } bits;
+};
+
+#define FP_DECL_E(X)		_FP_DECL(2,X)
+
+#define FP_UNPACK_RAW_E(X, val)					\
+  do {								\
+    union _FP_UNION_E _flo; _flo.flt = (val);			\
+								\
+    X##_f0 = _flo.bits.frac;					\
+    X##_f1 = 0;							\
+    X##_e = _flo.bits.exp;					\
+    X##_s = _flo.bits.sign;					\
+    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))		\
+      {								\
+        X##_e++;						\
+        FP_SET_EXCEPTION(FP_EX_DENORM);				\
+      }								\
+  } while (0)
+
+#define FP_UNPACK_RAW_EP(X, val)				\
+  do {								\
+    union _FP_UNION_E *_flo =					\
+      (union _FP_UNION_E *)(val);				\
+								\
+    X##_f0 = _flo->bits.frac;					\
+    X##_f1 = 0;							\
+    X##_e = _flo->bits.exp;					\
+    X##_s = _flo->bits.sign;					\
+    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))		\
+      {								\
+        X##_e++;						\
+        FP_SET_EXCEPTION(FP_EX_DENORM);				\
+      }								\
+  } while (0)
+
+#define FP_PACK_RAW_E(val, X)					\
+  do {								\
+    union _FP_UNION_E _flo;					\
+								\
+    if (X##_e) X##_f0 |= _FP_IMPLBIT_E;				\
+    else X##_f0 &= ~(_FP_IMPLBIT_E);				\
+    _flo.bits.frac = X##_f0;					\
+    _flo.bits.exp  = X##_e;					\
+    _flo.bits.sign = X##_s;					\
+								\
+    (val) = _flo.flt;						\
+  } while (0)
+
+#define FP_PACK_RAW_EP(fs, val, X)				\
+  do {								\
+    if (!FP_INHIBIT_RESULTS)					\
+      {								\
+	union _FP_UNION_E *_flo =				\
+	  (union _FP_UNION_E *)(val);				\
+								\
+	if (X##_e) X##_f0 |= _FP_IMPLBIT_E;			\
+	else X##_f0 &= ~(_FP_IMPLBIT_E);			\
+	_flo->bits.frac = X##_f0;				\
+	_flo->bits.exp  = X##_e;				\
+	_flo->bits.sign = X##_s;				\
+      }								\
+  } while (0)
+
+
+#define FP_UNPACK_E(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_E(X,val);		\
+    _FP_UNPACK_CANONICAL(E,2,X);	\
+  } while (0)
+
+#define FP_UNPACK_EP(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_EP(X,val);		\
+    _FP_UNPACK_CANONICAL(E,2,X);	\
+  } while (0)
+
+#define FP_PACK_E(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,2,X);		\
+    FP_PACK_RAW_E(val,X);		\
+  } while (0)
+
+#define FP_PACK_EP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,2,X);		\
+    FP_PACK_RAW_EP(val,X);		\
+  } while (0)
+
+#define FP_ISSIGNAN_E(X)	_FP_ISSIGNAN(E,2,X)
+#define FP_NEG_E(R,X)		_FP_NEG(E,2,R,X)
+#define FP_ADD_E(R,X,Y)		_FP_ADD(E,2,R,X,Y)
+#define FP_SUB_E(R,X,Y)		_FP_SUB(E,2,R,X,Y)
+#define FP_MUL_E(R,X,Y)		_FP_MUL(E,2,R,X,Y)
+#define FP_DIV_E(R,X,Y)		_FP_DIV(E,2,R,X,Y)
+#define FP_SQRT_E(R,X)		_FP_SQRT(E,2,R,X)
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ * We optimize it by doing most of the calculations
+ * in one UWtype registers instead of two, although we don't
+ * have to.
+ */
+#define _FP_SQRT_MEAT_E(R, S, T, X, q)			\
+  do {							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    _FP_FRAC_SRL_2(X, (_FP_WORKBITS));			\
+    while (q)						\
+      {							\
+        T##_f0 = S##_f0 + q;				\
+        if (T##_f0 <= X##_f0)				\
+          {						\
+            S##_f0 = T##_f0 + q;			\
+            X##_f0 -= T##_f0;				\
+            R##_f0 += q;				\
+          }						\
+        _FP_FRAC_SLL_1(X, 1);				\
+        q >>= 1;					\
+      }							\
+    _FP_FRAC_SLL_2(R, (_FP_WORKBITS));			\
+    if (X##_f0)						\
+      {							\
+	if (S##_f0 < X##_f0)				\
+	  R##_f0 |= _FP_WORK_ROUND;			\
+	R##_f0 |= _FP_WORK_STICKY;			\
+      }							\
+  } while (0)
+ 
+#define FP_CMP_E(r,X,Y,un)	_FP_CMP(E,2,r,X,Y,un)
+#define FP_CMP_EQ_E(r,X,Y)	_FP_CMP_EQ(E,2,r,X,Y)
+
+#define FP_TO_INT_E(r,X,rsz,rsg)	_FP_TO_INT(E,2,r,X,rsz,rsg)
+#define FP_FROM_INT_E(X,r,rs,rt)	_FP_FROM_INT(E,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_E(X)	(X##_f1)
+#define _FP_FRAC_HIGH_RAW_E(X)	(X##_f0)
+
+#endif /* not _FP_W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fabsq.c linux/arch/sparc64/math-emu/fabsq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fabsq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fabsq.c	Sat May 29 11:09:04 1999
@@ -1,3 +1,10 @@
+/* $Id: fabsq.c,v 1.5 1999/05/28 13:42:27 jj Exp $
+ * arch/sparc64/math-emu/fabsq.c
+ *
+ * Copyright (C) 1997 Jakub Jelinek (j...@ultra.linux.cz)
+ *
+ */
+
X int FABSQ(unsigned long *rd, unsigned long *rs2)
X {
X 	rd[0] = rs2[0] & 0x7fffffffffffffffUL;
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/faddd.c linux/arch/sparc64/math-emu/faddd.c
--- v2.3.3/linux/arch/sparc64/math-emu/faddd.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/faddd.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: faddd.c,v 1.4 1999/05/28 13:43:17 jj Exp $
+ * arch/sparc64/math-emu/faddd.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
X int FADDD(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
X 
-	__FP_UNPACK_D(A, rs1);
-	__FP_UNPACK_D(B, rs2);
+	FP_UNPACK_DP(A, rs1);
+	FP_UNPACK_DP(B, rs2);
X 	FP_ADD_D(R, A, B);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/faddq.c linux/arch/sparc64/math-emu/faddq.c
--- v2.3.3/linux/arch/sparc64/math-emu/faddq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/faddq.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: faddq.c,v 1.4 1999/05/28 13:43:19 jj Exp $
+ * arch/sparc64/math-emu/faddq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FADDQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
X 
-	__FP_UNPACK_Q(A, rs1);
-	__FP_UNPACK_Q(B, rs2);
+	FP_UNPACK_QP(A, rs1);
+	FP_UNPACK_QP(B, rs2);
X 	FP_ADD_Q(R, A, B);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fadds.c linux/arch/sparc64/math-emu/fadds.c
--- v2.3.3/linux/arch/sparc64/math-emu/fadds.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fadds.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fadds.c,v 1.4 1999/05/28 13:43:25 jj Exp $
+ * arch/sparc64/math-emu/fadds.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
X int FADDS(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
X 
-	__FP_UNPACK_S(A, rs1);
-	__FP_UNPACK_S(B, rs2);
+	FP_UNPACK_SP(A, rs1);
+	FP_UNPACK_SP(B, rs2);
X 	FP_ADD_S(R, A, B);
-	return __FP_PACK_S(rd, R);
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fcmpeq.c linux/arch/sparc64/math-emu/fcmpeq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fcmpeq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fcmpeq.c	Sat May 29 11:09:04 1999
@@ -1,25 +1,39 @@
+/* $Id: fcmpeq.c,v 1.5 1999/05/28 13:43:29 jj Exp $
+ * arch/sparc64/math-emu/fcmpeq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FCMPEQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(B);
X 	long ret;
-	int fccno = ((long)rd) & 3;
+	long fccno = (long)rd;
X 	unsigned long fsr;
X 	
-	rd = (void *)(((long)rd)&~3);
-	__FP_UNPACK_Q(A, rs1);
-	__FP_UNPACK_Q(B, rs2);
+	FP_UNPACK_RAW_QP(A, rs1);
+	FP_UNPACK_RAW_QP(B, rs2);
X 	FP_CMP_Q(ret, B, A, 3);
-	if (ret == -1) ret = 2;
-	fsr = *(unsigned long *)rd;
-	switch (fccno) {
-	case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
-	case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
-	case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
-	case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
+	if (ret == 3)
+		FP_SET_EXCEPTION(FP_EX_INVALID);
+	if (!FP_INHIBIT_RESULTS) {
+		rd = (void *)(((long)rd)&~3);
+		if (ret == -1) ret = 2;
+		fsr = current->tss.xfsr[0];
+		switch (fccno) {
+		case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
+		case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
+		case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
+		case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
+		}
+		current->tss.xfsr[0] = fsr;
X 	}
-	*(unsigned long *)rd = fsr;
-	return 0;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fcmpq.c linux/arch/sparc64/math-emu/fcmpq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fcmpq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fcmpq.c	Sat May 29 11:09:04 1999
@@ -1,25 +1,39 @@
+/* $Id: fcmpq.c,v 1.5 1999/05/28 13:43:33 jj Exp $
+ * arch/sparc64/math-emu/fcmpq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FCMPQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(B);
X 	long ret;
-	int fccno = ((long)rd) & 3;
+	long fccno = (long)rd;
X 	unsigned long fsr;
X 	
-	rd = (void *)(((long)rd)&~3);
-	__FP_UNPACK_Q(A, rs1);
-	__FP_UNPACK_Q(B, rs2);
+	FP_UNPACK_RAW_QP(A, rs1);
+	FP_UNPACK_RAW_QP(B, rs2);
X 	FP_CMP_Q(ret, B, A, 3);
-	if (ret == -1) ret = 2;
-	fsr = *(unsigned long *)rd;
-	switch (fccno) {
-	case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
-	case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
-	case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
-	case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
+	if (ret == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
+		FP_SET_EXCEPTION(FP_EX_INVALID);
+	if (!FP_INHIBIT_RESULTS) {
+		rd = (void *)(((long)rd)&~3);
+		if (ret == -1) ret = 2;
+		fsr = current->tss.xfsr[0];
+		switch (fccno) {
+		case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
+		case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
+		case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
+		case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
+		}
+		current->tss.xfsr[0] = fsr;
X 	}
-	*(unsigned long *)rd = fsr;
-	return 0;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdivd.c linux/arch/sparc64/math-emu/fdivd.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdivd.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdivd.c	Sat May 29 11:09:04 1999
@@ -1,19 +1,23 @@
+/* $Id: fdivd.c,v 1.4 1999/05/28 13:43:36 jj Exp $
+ * arch/sparc64/math-emu/fdivd.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
X int FDIVD(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-	int ret = 0;
X 
-	__FP_UNPACK_D(A, rs1);
-	__FP_UNPACK_D(B, rs2);
-	if(B_c == FP_CLS_ZERO &&
-	   A_c != FP_CLS_ZERO) {
-		ret |= EFLAG_DIVZERO;
-		if(__FPU_TRAP_P(EFLAG_DIVZERO))
-			return ret;
-	}
+	FP_UNPACK_DP(A, rs1);
+	FP_UNPACK_DP(B, rs2);
X 	FP_DIV_D(R, A, B);
-	return (ret | __FP_PACK_D(rd, R));
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdivq.c linux/arch/sparc64/math-emu/fdivq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdivq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdivq.c	Sat May 29 11:09:04 1999
@@ -1,19 +1,23 @@
+/* $Id: fdivq.c,v 1.4 1999/05/28 13:43:41 jj Exp $
+ * arch/sparc64/math-emu/fdivq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FDIVQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-	int ret;
X 
-	__FP_UNPACK_Q(A, rs1);
-	__FP_UNPACK_Q(B, rs2);
-	if(B_c == FP_CLS_ZERO &&
-	   A_c != FP_CLS_ZERO) {
-		ret |= EFLAG_DIVZERO;
-		if(__FPU_TRAP_P(EFLAG_DIVZERO))
-			return ret;
-	}
+	FP_UNPACK_QP(A, rs1);
+	FP_UNPACK_QP(B, rs2);
X 	FP_DIV_Q(R, A, B);
-	return (ret | __FP_PACK_Q(rd, R));
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdivs.c linux/arch/sparc64/math-emu/fdivs.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdivs.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdivs.c	Sat May 29 11:09:04 1999
@@ -1,20 +1,24 @@
+/* $Id: fdivs.c,v 1.4 1999/05/28 13:43:45 jj Exp $
+ * arch/sparc64/math-emu/fdivs.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
X int FDIVS(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-	int ret = 0;
X 
-	__FP_UNPACK_S(A, rs1);
-	__FP_UNPACK_S(B, rs2);
-	if(B_c == FP_CLS_ZERO &&
-	   A_c != FP_CLS_ZERO) {
-		ret |= EFLAG_DIVZERO;
-		if(__FPU_TRAP_P(EFLAG_DIVZERO))
-			return ret;
-	}
+	FP_UNPACK_SP(A, rs1);
+	FP_UNPACK_SP(B, rs2);
X 	FP_DIV_S(R, A, B);
-	return (ret | __FP_PACK_S(rd, R));
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
X 
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdmulq.c linux/arch/sparc64/math-emu/fdmulq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdmulq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdmulq.c	Sat May 29 11:09:04 1999
@@ -1,15 +1,26 @@
+/* $Id: fdmulq.c,v 1.4 1999/05/28 13:43:48 jj Exp $
+ * arch/sparc64/math-emu/fdmulq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X #include "double.h"
X 
X int FDMULQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(IN); FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
X 
-	__FP_UNPACK_D(IN, rs1);
+	FP_UNPACK_DP(IN, rs1);
X 	FP_CONV(Q,D,2,1,A,IN);
-	__FP_UNPACK_D(IN, rs2);
+	FP_UNPACK_DP(IN, rs2);
X 	FP_CONV(Q,D,2,1,B,IN);
X 	FP_MUL_Q(R, A, B);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdtoi.c linux/arch/sparc64/math-emu/fdtoi.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdtoi.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdtoi.c	Sat May 29 11:09:04 1999
@@ -1,13 +1,25 @@
+/* $Id: fdtoi.c,v 1.3 1999/05/28 13:43:52 jj Exp $
+ * arch/sparc64/math-emu/fdtoi.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#define FP_ROUNDMODE FP_RND_ZERO
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
-int FDTOI(unsigned *rd, void *rs2)
+int FDTOI(int *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A);
-	unsigned r;
+	int r;
X 
-	__FP_UNPACK_D(A, rs2);
+	FP_UNPACK_DP(A, rs2);
X 	FP_TO_INT_D(r, A, 32, 1);
-	*rd = r;
-	return 0;
+	if (!FP_INHIBIT_RESULTS)
+		*rd = r;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdtoq.c linux/arch/sparc64/math-emu/fdtoq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdtoq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdtoq.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fdtoq.c,v 1.4 1999/05/28 13:43:56 jj Exp $
+ * arch/sparc64/math-emu/fdtoq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X #include "double.h"
X 
X int FDTOQ(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_Q(R);
X 
-	__FP_UNPACK_D(A, rs2);
+	FP_UNPACK_DP(A, rs2);
X 	FP_CONV(Q,D,2,1,R,A);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdtos.c linux/arch/sparc64/math-emu/fdtos.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdtos.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdtos.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fdtos.c,v 1.4 1999/05/28 13:43:58 jj Exp $
+ * arch/sparc64/math-emu/fdtos.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X #include "single.h"
X 
X int FDTOS(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_S(R);
X 
-	__FP_UNPACK_D(A, rs2);
+	FP_UNPACK_DP(A, rs2);
X 	FP_CONV(S,D,1,1,R,A);
-	return __FP_PACK_S(rd, R);
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fdtox.c linux/arch/sparc64/math-emu/fdtox.c
--- v2.3.3/linux/arch/sparc64/math-emu/fdtox.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fdtox.c	Sat May 29 11:09:04 1999
@@ -1,13 +1,25 @@
+/* $Id: fdtox.c,v 1.3 1999/05/28 13:44:02 jj Exp $
+ * arch/sparc64/math-emu/fdtox.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#define FP_ROUNDMODE FP_RND_ZERO
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
-int FDTOX(unsigned long *rd, void *rs2)
+int FDTOX(long *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A);
-	unsigned long r;
+	long r;
X 
-	__FP_UNPACK_D(A, rs2);
+	FP_UNPACK_DP(A, rs2);
X 	FP_TO_INT_D(r, A, 64, 1);
-	*rd = r;
-	return 0;
+	if (!FP_INHIBIT_RESULTS)
+		*rd = r;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fitoq.c linux/arch/sparc64/math-emu/fitoq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fitoq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fitoq.c	Sat May 29 11:09:04 1999
@@ -1,11 +1,22 @@
+/* $Id: fitoq.c,v 1.5 1999/05/28 13:44:06 jj Exp $
+ * arch/sparc64/math-emu/fitoq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FITOQ(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(R);
X 	int a = *(int *)rs2;
X 
X 	FP_FROM_INT_Q(R, a, 32, int);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	return 0;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fmovq.c linux/arch/sparc64/math-emu/fmovq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fmovq.c	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fmovq.c	Sat May 29 11:09:04 1999
@@ -1,3 +1,10 @@
+/* $Id: fmovq.c,v 1.2 1999/05/28 13:44:09 jj Exp $
+ * arch/sparc64/math-emu/fmovq.c
+ *
+ * Copyright (C) 1997 Jakub Jelinek (j...@ultra.linux.cz)
+ *
+ */
+
X int FMOVQ(unsigned long *rd, unsigned long *rs2)
X {
X 	rd[0] = rs2[0];
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fmuld.c linux/arch/sparc64/math-emu/fmuld.c
--- v2.3.3/linux/arch/sparc64/math-emu/fmuld.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fmuld.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fmuld.c,v 1.4 1999/05/28 13:44:11 jj Exp $
+ * arch/sparc64/math-emu/fmuld.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
X int FMULD(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
X 
-	__FP_UNPACK_D(A, rs1);
-	__FP_UNPACK_D(B, rs2);
+	FP_UNPACK_DP(A, rs1);
+	FP_UNPACK_DP(B, rs2);
X 	FP_MUL_D(R, A, B);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fmulq.c linux/arch/sparc64/math-emu/fmulq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fmulq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fmulq.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fmulq.c,v 1.4 1999/05/28 13:44:14 jj Exp $
+ * arch/sparc64/math-emu/fmulq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FMULQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
X 
-	__FP_UNPACK_Q(A, rs1);
-	__FP_UNPACK_Q(B, rs2);
+	FP_UNPACK_QP(A, rs1);
+	FP_UNPACK_QP(B, rs2);
X 	FP_MUL_Q(R, A, B);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fmuls.c linux/arch/sparc64/math-emu/fmuls.c
--- v2.3.3/linux/arch/sparc64/math-emu/fmuls.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fmuls.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fmuls.c,v 1.4 1999/05/28 13:44:18 jj Exp $
+ * arch/sparc64/math-emu/fmuls.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
X int FMULS(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
X 
-	__FP_UNPACK_S(A, rs1);
-	__FP_UNPACK_S(B, rs2);
+	FP_UNPACK_SP(A, rs1);
+	FP_UNPACK_SP(B, rs2);
X 	FP_MUL_S(R, A, B);
-	return __FP_PACK_S(rd, R);
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fnegq.c linux/arch/sparc64/math-emu/fnegq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fnegq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fnegq.c	Sat May 29 11:09:04 1999
@@ -1,7 +1,13 @@
+/* $Id: fnegq.c,v 1.6 1999/05/28 13:44:21 jj Exp $
+ * arch/sparc64/math-emu/fnegq.c
+ *
+ * Copyright (C) 1997 Jakub Jelinek (j...@ultra.linux.cz)
+ *
+ */
+
X int FNEGQ(unsigned long *rd, unsigned long *rs2)
X {
X 	rd[0] = rs2[0] ^ 0x8000000000000000UL;
X 	rd[1] = rs2[1];
X 	return 0;
X }
-
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fqtod.c linux/arch/sparc64/math-emu/fqtod.c
--- v2.3.3/linux/arch/sparc64/math-emu/fqtod.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fqtod.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fqtod.c,v 1.4 1999/05/28 13:44:24 jj Exp $
+ * arch/sparc64/math-emu/fqtod.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X #include "double.h"
X 
X int FQTOD(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_D(R);
X 
-	__FP_UNPACK_Q(A, rs2);
+	FP_UNPACK_QP(A, rs2);
X 	FP_CONV(D,Q,1,2,R,A);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fqtoi.c linux/arch/sparc64/math-emu/fqtoi.c
--- v2.3.3/linux/arch/sparc64/math-emu/fqtoi.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fqtoi.c	Sat May 29 11:09:04 1999
@@ -1,13 +1,25 @@
+/* $Id: fqtoi.c,v 1.4 1999/05/28 13:44:26 jj Exp $
+ * arch/sparc64/math-emu/fqtoi.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#define FP_ROUNDMODE FP_RND_ZERO
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
-int FQTOI(unsigned *rd, void *rs2)
+int FQTOI(int *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A);
-	unsigned r;
+	int r;
X 
-	__FP_UNPACK_Q(A, rs2);
+	FP_UNPACK_QP(A, rs2);
X 	FP_TO_INT_Q(r, A, 32, 1);
-	*rd = r;
-	return 0;
+	if (!FP_INHIBIT_RESULTS)
+		*rd = r;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fqtos.c linux/arch/sparc64/math-emu/fqtos.c
--- v2.3.3/linux/arch/sparc64/math-emu/fqtos.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fqtos.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fqtos.c,v 1.4 1999/05/28 13:44:30 jj Exp $
+ * arch/sparc64/math-emu/fqtos.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X #include "single.h"
X 
X int FQTOS(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_S(R);
X 
-	__FP_UNPACK_Q(A, rs2);
+	FP_UNPACK_QP(A, rs2);
X 	FP_CONV(S,Q,1,2,R,A);
-	return __FP_PACK_S(rd, R);
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fqtox.c linux/arch/sparc64/math-emu/fqtox.c
--- v2.3.3/linux/arch/sparc64/math-emu/fqtox.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fqtox.c	Sat May 29 11:09:04 1999
@@ -1,13 +1,25 @@
+/* $Id: fqtox.c,v 1.4 1999/05/28 13:44:34 jj Exp $
+ * arch/sparc64/math-emu/fqtox.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#define FP_ROUNDMODE FP_RND_ZERO
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
-int FQTOX(unsigned long *rd, void *rs2)
+int FQTOX(long *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A);
-	unsigned long r;
+	long r;
X 
-	__FP_UNPACK_Q(A, rs2);
+	FP_UNPACK_QP(A, rs2);
X 	FP_TO_INT_Q(r, A, 64, 1);
-	*rd = r;
-	return 0;
+	if (!FP_INHIBIT_RESULTS)
+		*rd = r;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsmuld.c linux/arch/sparc64/math-emu/fsmuld.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsmuld.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsmuld.c	Sat May 29 11:09:04 1999
@@ -1,15 +1,26 @@
+/* $Id: fsmuld.c,v 1.4 1999/05/28 13:44:37 jj Exp $
+ * arch/sparc64/math-emu/fsmuld.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X #include "single.h"
X 
X int FSMULD(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(IN); FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
X 
-	__FP_UNPACK_S(IN, rs1);
+	FP_UNPACK_SP(IN, rs1);
X 	FP_CONV(D,S,1,1,A,IN);
-	__FP_UNPACK_S(IN, rs2);
+	FP_UNPACK_SP(IN, rs2);
X 	FP_CONV(D,S,1,1,B,IN);
X 	FP_MUL_D(R, A, B);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsqrtd.c linux/arch/sparc64/math-emu/fsqrtd.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsqrtd.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsqrtd.c	Sat May 29 11:09:04 1999
@@ -1,11 +1,22 @@
+/* $Id: fsqrtd.c,v 1.4 1999/05/28 13:44:39 jj Exp $
+ * arch/sparc64/math-emu/fsqrtd.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
X int FSQRTD(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_D(R);
X         
-	__FP_UNPACK_D(A, rs2);
+	FP_UNPACK_DP(A, rs2);
X 	FP_SQRT_D(R, A);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsqrtq.c linux/arch/sparc64/math-emu/fsqrtq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsqrtq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsqrtq.c	Sat May 29 11:09:04 1999
@@ -1,11 +1,22 @@
+/* $Id: fsqrtq.c,v 1.5 1999/05/28 13:44:44 jj Exp $
+ * arch/sparc64/math-emu/fsqrtq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FSQRTQ(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(R);
X         
-	__FP_UNPACK_Q(A, rs2);
+	FP_UNPACK_QP(A, rs2);
X 	FP_SQRT_Q(R, A);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsqrts.c linux/arch/sparc64/math-emu/fsqrts.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsqrts.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsqrts.c	Sat May 29 11:09:04 1999
@@ -1,11 +1,22 @@
+/* $Id: fsqrts.c,v 1.4 1999/05/28 13:44:48 jj Exp $
+ * arch/sparc64/math-emu/fsqrts.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
X int FSQRTS(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_S(R);
X         
-	__FP_UNPACK_S(A, rs2);
+	FP_UNPACK_SP(A, rs2);
X 	FP_SQRT_S(R, A);
-	return __FP_PACK_S(rd, R);
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fstod.c linux/arch/sparc64/math-emu/fstod.c
--- v2.3.3/linux/arch/sparc64/math-emu/fstod.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fstod.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fstod.c,v 1.4 1999/05/28 13:44:51 jj Exp $
+ * arch/sparc64/math-emu/fstod.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X #include "single.h"
X 
X int FSTOD(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_D(R);
X 
-	__FP_UNPACK_S(A, rs2);
+	FP_UNPACK_SP(A, rs2);
X 	FP_CONV(D,S,1,1,R,A);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fstoi.c linux/arch/sparc64/math-emu/fstoi.c
--- v2.3.3/linux/arch/sparc64/math-emu/fstoi.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fstoi.c	Sat May 29 11:09:04 1999
@@ -1,13 +1,25 @@
+/* $Id: fstoi.c,v 1.3 1999/05/28 13:44:54 jj Exp $
+ * arch/sparc64/math-emu/fstoi.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#define FP_ROUNDMODE FP_RND_ZERO
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
-int FSTOI(unsigned *rd, void *rs2)
+int FSTOI(int *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A);
-	unsigned r;
+	int r;
X 
-	__FP_UNPACK_S(A, rs2);
+	FP_UNPACK_SP(A, rs2);
X 	FP_TO_INT_S(r, A, 32, 1);
-	*rd = r;
-	return 0;
+	if (!FP_INHIBIT_RESULTS)
+		*rd = r;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fstoq.c linux/arch/sparc64/math-emu/fstoq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fstoq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fstoq.c	Sat May 29 11:09:04 1999
@@ -1,12 +1,23 @@
+/* $Id: fstoq.c,v 1.4 1999/05/28 13:44:58 jj Exp $
+ * arch/sparc64/math-emu/fstoq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X #include "single.h"
X 
X int FSTOQ(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_Q(R);
X 
-	__FP_UNPACK_S(A, rs2);
+	FP_UNPACK_SP(A, rs2);
X 	FP_CONV(Q,S,2,1,R,A);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fstox.c linux/arch/sparc64/math-emu/fstox.c
--- v2.3.3/linux/arch/sparc64/math-emu/fstox.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fstox.c	Sat May 29 11:09:04 1999
@@ -1,13 +1,25 @@
+/* $Id: fstox.c,v 1.3 1999/05/28 13:45:01 jj Exp $
+ * arch/sparc64/math-emu/fstox.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#define FP_ROUNDMODE FP_RND_ZERO
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
-int FSTOX(unsigned long *rd, void *rs2)
+int FSTOX(long *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A);
-	unsigned long r;
+	long r;
X 
-	__FP_UNPACK_S(A, rs2);
+	FP_UNPACK_SP(A, rs2);
X 	FP_TO_INT_S(r, A, 64, 1);
-	*rd = r;
-	return 0;
+	if (!FP_INHIBIT_RESULTS)
+		*rd = r;
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsubd.c linux/arch/sparc64/math-emu/fsubd.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsubd.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsubd.c	Sat May 29 11:09:04 1999
@@ -1,14 +1,25 @@
+/* $Id: fsubd.c,v 1.4 1999/05/28 13:45:04 jj Exp $
+ * arch/sparc64/math-emu/fsubd.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "double.h"
X 
X int FSUBD(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
X 
-	__FP_UNPACK_D(A, rs1);
-	__FP_UNPACK_D(B, rs2);
+	FP_UNPACK_DP(A, rs1);
+	FP_UNPACK_DP(B, rs2);
X 	if (B_c != FP_CLS_NAN)
X 		B_s ^= 1;
X 	FP_ADD_D(R, A, B);
-	return __FP_PACK_D(rd, R);
+	FP_PACK_DP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsubq.c linux/arch/sparc64/math-emu/fsubq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsubq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsubq.c	Sat May 29 11:09:04 1999
@@ -1,14 +1,25 @@
+/* $Id: fsubq.c,v 1.4 1999/05/28 13:45:09 jj Exp $
+ * arch/sparc64/math-emu/fsubq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FSUBQ(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
X 
-	__FP_UNPACK_Q(A, rs1);
-	__FP_UNPACK_Q(B, rs2);
+	FP_UNPACK_QP(A, rs1);
+	FP_UNPACK_QP(B, rs2);
X 	if (B_c != FP_CLS_NAN)
X 		B_s ^= 1;
X 	FP_ADD_Q(R, A, B);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fsubs.c linux/arch/sparc64/math-emu/fsubs.c
--- v2.3.3/linux/arch/sparc64/math-emu/fsubs.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fsubs.c	Sat May 29 11:09:04 1999
@@ -1,14 +1,25 @@
+/* $Id: fsubs.c,v 1.4 1999/05/28 13:45:12 jj Exp $
+ * arch/sparc64/math-emu/fsubs.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "single.h"
X 
X int FSUBS(void *rd, void *rs2, void *rs1)
X {
+	FP_DECL_EX;
X 	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
X 
-	__FP_UNPACK_S(A, rs1);
-	__FP_UNPACK_S(B, rs2);
+	FP_UNPACK_SP(A, rs1);
+	FP_UNPACK_SP(B, rs2);
X 	if (B_c != FP_CLS_NAN)
X 		B_s ^= 1;
X 	FP_ADD_S(R, A, B);
-	return __FP_PACK_S(rd, R);
+	FP_PACK_SP(rd, R);
+	FP_HANDLE_EXCEPTIONS;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/fxtoq.c linux/arch/sparc64/math-emu/fxtoq.c
--- v2.3.3/linux/arch/sparc64/math-emu/fxtoq.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/fxtoq.c	Sat May 29 11:09:04 1999
@@ -1,11 +1,22 @@
+/* $Id: fxtoq.c,v 1.5 1999/05/28 13:45:15 jj Exp $
+ * arch/sparc64/math-emu/fxtoq.c
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
+ *
+ */
+
+#include "sfp-util.h"
X #include "soft-fp.h"
X #include "quad.h"
X 
X int FXTOQ(void *rd, void *rs2)
X {
+	FP_DECL_EX;
X 	FP_DECL_Q(R);
X 	long a = *(long *)rs2;
X 
X 	FP_FROM_INT_Q(R, a, 64, long);
-	return __FP_PACK_Q(rd, R);
+	FP_PACK_QP(rd, R);
+	return 0;
X }
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/math.c linux/arch/sparc64/math-emu/math.c
--- v2.3.3/linux/arch/sparc64/math-emu/math.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/math.c	Sat May 29 11:09:04 1999
@@ -1,7 +1,7 @@
-/* $Id: math.c,v 1.7 1999/02/10 14:16:26 davem Exp $
+/* $Id: math.c,v 1.8 1999/05/28 13:43:11 jj Exp $
X  * arch/sparc64/math-emu/math.c
X  *
- * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1999 Jakub Jelinek (j...@ultra.linux.cz)
X  * Copyright (C) 1999 David S. Miller (da...@redhat.com)
X  *
X  * Emulation routines originate from soft-fp package, which is part
@@ -15,6 +15,7 @@
X #include <asm/ptrace.h>
X #include <asm/uaccess.h>
X 
+#include "sfp-util.h"
X #include "soft-fp.h"
X 
X #define FLOATFUNC(x) extern int x(void *,void *,void *);
@@ -84,46 +85,36 @@
X 	if(would_trap != 0) {
X 		eflag &= ((fsr & FSR_TEM_MASK) >> FSR_TEM_SHIFT);
X 		if((eflag & (eflag - 1)) != 0) {
-			if(eflag & EFLAG_INVALID)
-				eflag = EFLAG_INVALID;
-			else if(eflag & EFLAG_DIVZERO)
-				eflag = EFLAG_DIVZERO;
-			else if(eflag & EFLAG_INEXACT)
-				eflag = EFLAG_INEXACT;
+			if(eflag & FP_EX_INVALID)
+				eflag = FP_EX_INVALID;
+			else if(eflag & FP_EX_OVERFLOW)
+				eflag = FP_EX_OVERFLOW;
+			else if(eflag & FP_EX_UNDERFLOW)
+				eflag = FP_EX_UNDERFLOW;
+			else if(eflag & FP_EX_DIVZERO)
+				eflag = FP_EX_DIVZERO;
+			else if(eflag & FP_EX_INEXACT)
+				eflag = FP_EX_INEXACT;
X 		}
X 	}
X 
-	/* Set CEXC, here are the rules:
+	/* Set CEXC, here is the rule:
X 	 *
-	 * 1) In general all FPU ops will set one and only one
+	 *    In general all FPU ops will set one and only one
X 	 *    bit in the CEXC field, this is always the case
X 	 *    when the IEEE exception trap is enabled in TEM.
-	 *
-	 * 2) As a special case, if an overflow or underflow
-	 *    is being signalled, AND the trap is not enabled
-	 *    in TEM, then the inexact field shall also be set.
X 	 */
X 	fsr &= ~(FSR_CEXC_MASK);
-	if(would_trap ||
-	   (eflag & (EFLAG_OVERFLOW | EFLAG_UNDERFLOW)) == 0) {
-		fsr |= ((long)eflag << FSR_CEXC_SHIFT);
-	} else {
-		fsr |= (((long)eflag << FSR_CEXC_SHIFT) |
-			(EFLAG_INEXACT << FSR_CEXC_SHIFT));
-	}
+	fsr |= ((long)eflag << FSR_CEXC_SHIFT);
X 
-	/* Set the AEXC field, rules are:
+	/* Set the AEXC field, rule is:
X 	 *
-	 * 1) If a trap would not be generated, the
+	 *    If a trap would not be generated, the
X 	 *    CEXC just generated is OR'd into the
X 	 *    existing value of AEXC.
-	 *
-	 * 2) When a trap is generated, AEXC is cleared.
X 	 */
X 	if(would_trap == 0)
X 		fsr |= ((long)eflag << FSR_AEXC_SHIFT);
-	else
-		fsr &= ~(FSR_AEXC_MASK);
X 
X 	/* If trapping, indicate fault trap type IEEE. */
X 	if(would_trap != 0)
@@ -242,7 +233,7 @@
X 		}
X 		freg = ((insn >> 25) & 0x1f);
X 		switch ((type >> 4) & 0x3) {
-		case 0: rd = (void *)(((long)¤t->tss.xfsr[0]) | (freg & 3)); break;
+		case 0: rd = (void *)(long)(freg & 3); break;
X 		case 3: if (freg & 2) {
X 				current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
X 				goto err;
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/op-1.h linux/arch/sparc64/math-emu/op-1.h
--- v2.3.3/linux/arch/sparc64/math-emu/op-1.h	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/op-1.h	Sat May 29 11:09:04 1999
@@ -1,6 +1,26 @@
-/*
- * Basic one-word fraction declaration and manipulation.
- */
+/* Software floating-point emulation.
+   Basic one-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (r...@cygnus.com),
+		  Jakub Jelinek (j...@ultra.linux.cz),
+		  David S. Miller (da...@redhat.com) and
+		  Peter Maydell (pmay...@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
X 
X #define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
X #define _FP_FRAC_COPY_1(D,S)	(D##_f = S##_f)
@@ -28,6 +48,7 @@
X 
X #define _FP_FRAC_ADD_1(R,X,Y)	(R##_f = X##_f + Y##_f)
X #define _FP_FRAC_SUB_1(R,X,Y)	(R##_f = X##_f - Y##_f)
+#define _FP_FRAC_DEC_1(X,Y)	(X##_f -= Y##_f)
X #define _FP_FRAC_CLZ_1(z, X)	__FP_CLZ(z, X##_f)
X 
X /* Predicates */
@@ -40,6 +61,7 @@
X 
X #define _FP_ZEROFRAC_1		0
X #define _FP_MINFRAC_1		1
+#define _FP_MAXFRAC_1		(~(_FP_WS_TYPE)0)
X 
X /*
X  * Unpack the raw bits of a native fp value.  Do not classify or
@@ -55,6 +77,15 @@
X     X##_s = _flo.bits.sign;					\
X   } while (0)
X 
+#define _FP_UNPACK_RAW_1_P(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    X##_f = _flo->bits.frac;					\
+    X##_e = _flo->bits.exp;					\
+    X##_s = _flo->bits.sign;					\
+  } while (0)
X 
X /*
X  * Repack the raw bits of a native fp value.
@@ -71,6 +102,16 @@
X     (val) = _flo.flt;						\
X   } while (0)
X 
+#define _FP_PACK_RAW_1_P(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    _flo->bits.frac = X##_f;					\
+    _flo->bits.exp  = X##_e;					\
+    _flo->bits.sign = X##_s;					\
+  } while (0)
+
X 
X /*
X  * Multiplication algorithms:
@@ -207,7 +248,7 @@
X  
X #define _FP_SQRT_MEAT_1(R, S, T, X, q)			\
X   do {							\
-    while (q)						\
+    while (q != _FP_WORK_ROUND)				\
X       {							\
X         T##_f = S##_f + q;				\
X         if (T##_f <= X##_f)				\
@@ -219,6 +260,12 @@
X         _FP_FRAC_SLL_1(X, 1);				\
X         q >>= 1;					\
X       }							\
+    if (X##_f)						\
+      {							\
+	if (S##_f < X##_f)				\
+	  R##_f |= _FP_WORK_ROUND;			\
+	R##_f |= _FP_WORK_STICKY;			\
+      }							\
X   } while (0)
X 
X /*
@@ -238,8 +285,13 @@
X   do {									\
X     D##_f = S##_f;							\
X     if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs)			\
-      _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),	\
-		     _FP_WFRACBITS_##sfs);				\
+      {									\
+	if (S##_c != FP_CLS_NAN)					\
+	  _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),	\
+			 _FP_WFRACBITS_##sfs);				\
+	else								\
+	  _FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs));	\
+      }									\
X     else								\
X       D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;		\
X   } while (0)
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/op-2.h linux/arch/sparc64/math-emu/op-2.h
--- v2.3.3/linux/arch/sparc64/math-emu/op-2.h	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/op-2.h	Sat May 29 11:09:04 1999
@@ -1,6 +1,26 @@
-/*
- * Basic two-word fraction declaration and manipulation.
- */
+/* Software floating-point emulation.
+   Basic two-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (r...@cygnus.com),
+		  Jakub Jelinek (j...@ultra.linux.cz),
+		  David S. Miller (da...@redhat.com) and
+		  Peter Maydell (pmay...@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
X 
X #define _FP_FRAC_DECL_2(X)	_FP_W_TYPE X##_f0, X##_f1
X #define _FP_FRAC_COPY_2(D,S)	(D##_f0 = S##_f0, D##_f1 = S##_f1)
@@ -13,13 +33,13 @@
X   do {									\
X     if ((N) < _FP_W_TYPE_SIZE)						\
X       {									\
-        if (__builtin_constant_p(N) && (N) == 1) 			\
-          {								\
-            X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);	\
-            X##_f0 += X##_f0;						\
-          }								\
-        else								\
-          {								\
+	if (__builtin_constant_p(N) && (N) == 1) 			\
+	  {								\
+	    X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);	\
+	    X##_f0 += X##_f0;						\
+	  }								\
+	else								\
+	  {								\
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 08'
echo 'File patch-2.3.4 is continued in part 09'
echo 09 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 09 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X 	    X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N));	\
X 	    X##_f0 <<= (N);						\
X 	  }								\
@@ -59,20 +79,23 @@
X     else								\
X       {									\
X 	X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |			\
-	          (((X##_f1 << (sz - (N))) | X##_f0) != 0));		\
+		  (((X##_f1 << (sz - (N))) | X##_f0) != 0));		\
X 	X##_f1 = 0;							\
X       }									\
X   } while (0)
X 
-#define _FP_FRAC_ADDI_2(X,I) \
+#define _FP_FRAC_ADDI_2(X,I)	\
X   __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
X 
-#define _FP_FRAC_ADD_2(R,X,Y) \
+#define _FP_FRAC_ADD_2(R,X,Y)	\
X   __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
X 
-#define _FP_FRAC_SUB_2(R,X,Y) \
+#define _FP_FRAC_SUB_2(R,X,Y)	\
X   __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
X 
+#define _FP_FRAC_DEC_2(X,Y)	\
+  __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
+
X #define _FP_FRAC_CLZ_2(R,X)	\
X   do {				\
X     if (X##_f1)			\
@@ -87,7 +110,7 @@
X /* Predicates */
X #define _FP_FRAC_NEGP_2(X)	((_FP_WS_TYPE)X##_f1 < 0)
X #define _FP_FRAC_ZEROP_2(X)	((X##_f1 | X##_f0) == 0)
-#define _FP_FRAC_OVERP_2(fs,X)	(X##_f1 & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_OVERP_2(fs,X)	(_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
X #define _FP_FRAC_EQ_2(X, Y)	(X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
X #define _FP_FRAC_GT_2(X, Y)	\
X   (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 > Y##_f0)
@@ -96,6 +119,7 @@
X 
X #define _FP_ZEROFRAC_2		0, 0
X #define _FP_MINFRAC_2		0, 1
+#define _FP_MAXFRAC_2		(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
X 
X /*
X  * Internals 
@@ -106,7 +130,7 @@
X #define __FP_CLZ_2(R, xh, xl)	\
X   do {				\
X     if (xh)			\
-      __FP_CLZ(R,xl);		\
+      __FP_CLZ(R,xh);		\
X     else 			\
X     {				\
X       __FP_CLZ(R,xl);		\
@@ -117,17 +141,24 @@
X #if 0
X 
X #ifndef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i) \
+#define __FP_FRAC_ADDI_2(xh, xl, i)	\
X   (xh += ((xl += i) < i))
X #endif
X #ifndef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
+#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl)	\
X   (rh = xh + yh + ((rl = xl + yl) < xl))
X #endif
X #ifndef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
+#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl)	\
X   (rh = xh - yh - ((rl = xl - yl) > xl))
X #endif
+#ifndef __FP_FRAC_DEC_2
+#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	\
+  do {					\
+    UWtype _t = xl;			\
+    xh -= yh + ((xl -= yl) > _t);	\
+  } while (0)
+#endif
X 
X #else
X 
@@ -137,6 +168,8 @@
X #define __FP_FRAC_ADD_2			add_ssaaaa
X #undef __FP_FRAC_SUB_2
X #define __FP_FRAC_SUB_2			sub_ddmmss
+#undef __FP_FRAC_DEC_2
+#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	sub_ddmmss(xh, xl, xh, xl, yh, yl)
X 
X #endif
X 
@@ -155,6 +188,17 @@
X     X##_s  = _flo.bits.sign;				\
X   } while (0)
X 
+#define _FP_UNPACK_RAW_2_P(fs, X, val) \
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+      (union _FP_UNION_##fs *)(val);			\
+							\
+    X##_f0 = _flo->bits.frac0;				\
+    X##_f1 = _flo->bits.frac1;				\
+    X##_e  = _flo->bits.exp;				\
+    X##_s  = _flo->bits.sign;				\
+  } while (0)
+
X 
X /*
X  * Repack the raw bits of a native fp value.
@@ -172,6 +216,17 @@
X     (val) = _flo.flt;					\
X   } while (0)
X 
+#define _FP_PACK_RAW_2_P(fs, val, X) \
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+      (union _FP_UNION_##fs *)(val);			\
+							\
+    _flo->bits.frac0 = X##_f0;				\
+    _flo->bits.frac1 = X##_f1;				\
+    _flo->bits.exp   = X##_e;				\
+    _flo->bits.sign  = X##_s;				\
+  } while (0)
+
X 
X /*
X  * Multiplication algorithms:
@@ -183,21 +238,63 @@
X   do {									\
X     _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
X 									\
-    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
+    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);	\
X     doit(_b_f1, _b_f0, X##_f0, Y##_f1);					\
X     doit(_c_f1, _c_f0, X##_f1, Y##_f0);					\
-    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
+    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1);	\
X 									\
-    __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0),	\
-		    0, _b_f1, _b_f0, 0,					\
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0,		\
X 		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0));	\
-    __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0),	\
-		    0, _c_f1, _c_f0, 0,					\
+		    _FP_FRAC_WORD_4(_z,1));				\
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0,		\
X 		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0));	\
+		    _FP_FRAC_WORD_4(_z,1));				\
+									\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);	\
+    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
+    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
+  } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
+   Do only 3 multiplications instead of four. This one is for machines
+   where multiplication is much more expensive than subtraction.  */
+
+#define _FP_MUL_MEAT_2_wide_3mul(fs, R, X, Y, doit)			\
+  do {									\
+    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
+    _FP_W_TYPE _d;							\
+    int _c1, _c2;							\
+									\
+    _b_f0 = X##_f0 + X##_f1;						\
+    _c1 = _b_f0 < X##_f0;						\
+    _b_f1 = Y##_f0 + Y##_f1;						\
+    _c2 = _b_f1 < Y##_f0;						\
+    doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);			\
+    doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1);	\
+    doit(_c_f1, _c_f0, X##_f1, Y##_f1);					\
+									\
+    _b_f0 &= -_c2;							\
+    _b_f1 &= -_c1;							\
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d,		\
+		    0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1));	\
+    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		     _b_f0);						\
+    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		     _b_f1);						\
+    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1),				\
+		    0, _d, _FP_FRAC_WORD_4(_z,0));			\
+    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0);		\
+    __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2),	\
+		    _c_f1, _c_f0,					\
+		    _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2));	\
X 									\
X     /* Normalize since we know where the msb of the multiplicands	\
X        were (bit B), we know that the msb of the of the product is	\
@@ -207,118 +304,93 @@
X     R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
X   } while (0)
X 
-/* This next macro appears to be totally broken. Fortunately nowhere
- * seems to use it :-> The problem is that we define _z[4] but
- * then use it in _FP_FRAC_SRS_4, which will attempt to access
- * _z_f[n] which will cause an error. The fix probably involves 
- * declaring it with _FP_FRAC_DECL_4, see previous macro. -- PMM 02/1998 
- */
X #define _FP_MUL_MEAT_2_gmp(fs, R, X, Y)					\
X   do {									\
-    _FP_W_TYPE _x[2], _y[2], _z[4];					\
+    _FP_FRAC_DECL_4(_z);						\
+    _FP_W_TYPE _x[2], _y[2];						\
X     _x[0] = X##_f0; _x[1] = X##_f1;					\
X     _y[0] = Y##_f0; _y[1] = Y##_f1;					\
X 									\
-    mpn_mul_n(_z, _x, _y, 2);						\
+    mpn_mul_n(_z_f, _x, _y, 2);						\
X 									\
X     /* Normalize since we know where the msb of the multiplicands	\
X        were (bit B), we know that the msb of the of the product is	\
X        at either 2B or 2B-1.  */					\
X     _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs);	\
-    R##_f0 = _z[0];							\
-    R##_f1 = _z[1];							\
+    R##_f0 = _z_f[0];							\
+    R##_f1 = _z_f[1];							\
X   } while (0)
X 
X 
X /*
X  * Division algorithms:
- * This seems to be giving me difficulties -- PMM 
- * Look, NetBSD seems to be able to comment algorithms. Can't you?
- * I've thrown printks at the problem.
- * This now appears to work, but I still don't really know why.
- * Also, I don't think the result is properly normalised...
X  */
X 
-#define _FP_DIV_MEAT_2_udiv_64(fs, R, X, Y)				\
+#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y)				\
X   do {									\
-    extern void _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2],	\
-			       _FP_W_TYPE n1, _FP_W_TYPE n0,		\
-			       _FP_W_TYPE d1, _FP_W_TYPE d0);		\
-    _FP_W_TYPE _n_f3, _n_f2, _n_f1, _n_f0, _r_f1, _r_f0;		\
-    _FP_W_TYPE _q_f1, _q_f0, _m_f1, _m_f0;				\
-    _FP_W_TYPE _rmem[2], _qmem[2];					\
-    /* I think this check is to ensure that the result is normalised.   \
-     * Assuming X,Y normalised (ie in [1.0,2.0)) X/Y will be in         \
-     * [0.5,2.0). Furthermore, it will be less than 1.0 iff X < Y.      \
-     * In this case we tweak things. (this is based on comments in      \
-     * the NetBSD FPU emulation code. )                                 \
-     * We know X,Y are normalised because we ensure this as part of     \
-     * the unpacking process. -- PMM                                    \
-     */									\
+    _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0;		\
X     if (_FP_FRAC_GT_2(X, Y))						\
X       {									\
-/*	R##_e++; */							\
-	_n_f3 = X##_f1 >> 1;						\
-	_n_f2 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
-	_n_f1 = X##_f0 << (_FP_W_TYPE_SIZE - 1);			\
-	_n_f0 = 0;							\
+	_n_f2 = X##_f1 >> 1;						\
+	_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
+	_n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1);			\
X       }									\
X     else								\
X       {									\
X 	R##_e--;							\
-	_n_f3 = X##_f1;							\
-	_n_f2 = X##_f0;							\
-	_n_f1 = _n_f0 = 0;						\
+	_n_f2 = X##_f1;							\
+	_n_f1 = X##_f0;							\
+	_n_f0 = 0;							\
X       }									\
X 									\
X     /* Normalize, i.e. make the most significant bit of the 		\
-       denominator set.  CHANGED: - 1 to nothing -- PMM */		\
-    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs /* -1 */);			\
-									\
-    /* Do the 256/128 bit division given the 128-bit _fp_udivmodtf4 	\
-       primitive snagged from libgcc2.c.  */				\
+       denominator set. */						\
+    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs);				\
X 									\
-    _fp_udivmodti4(_qmem, _rmem, _n_f3, _n_f2, 0, Y##_f1);		\
-    _q_f1 = _qmem[0];							\
-    umul_ppmm(_m_f1, _m_f0, _q_f1, Y##_f0);				\
-    _r_f1 = _rmem[0];							\
-    _r_f0 = _n_f1;							\
+    udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1);			\
+    umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0);				\
+    _r_f0 = _n_f0;							\
X     if (_FP_FRAC_GT_2(_m, _r))						\
X       {									\
-	_q_f1--;							\
-	_FP_FRAC_ADD_2(_r, _r, Y);					\
+	R##_f1--;							\
+	_FP_FRAC_ADD_2(_r, Y, _r);					\
X 	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
X 	  {								\
-	    _q_f1--;							\
-	    _FP_FRAC_ADD_2(_r, _r, Y);					\
+	    R##_f1--;							\
+	    _FP_FRAC_ADD_2(_r, Y, _r);					\
X 	  }								\
X       }									\
-    _FP_FRAC_SUB_2(_r, _r, _m);						\
+    _FP_FRAC_DEC_2(_r, _m);						\
X 									\
-    _fp_udivmodti4(_qmem, _rmem, _r_f1, _r_f0, 0, Y##_f1);		\
-    _q_f0 = _qmem[0];							\
-    umul_ppmm(_m_f1, _m_f0, _q_f0, Y##_f0);				\
-    _r_f1 = _rmem[0];							\
-    _r_f0 = _n_f0;							\
-    if (_FP_FRAC_GT_2(_m, _r))						\
+    if (_r_f1 == Y##_f1)						\
X       {									\
-	_q_f0--;							\
-	_FP_FRAC_ADD_2(_r, _r, Y);					\
-	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
+	/* This is a special case, not an optimization			\
+	   (_r/Y##_f1 would not fit into UWtype).			\
+	   As _r is guaranteed to be < Y,  R##_f0 can be either		\
+	   (UWtype)-1 or (UWtype)-2.  But as we know what kind		\
+	   of bits it is (sticky, guard, round),  we don't care.	\
+	   We also don't care what the reminder is,  because the	\
+	   guard bit will be set anyway.  -jj */			\
+	R##_f0 = -1;							\
+      }									\
+    else								\
+      {									\
+	udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1);		\
+	umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0);			\
+	_r_f0 = 0;							\
+	if (_FP_FRAC_GT_2(_m, _r))					\
X 	  {								\
-	    _q_f0--;							\
-	    _FP_FRAC_ADD_2(_r, _r, Y);					\
+	    R##_f0--;							\
+	    _FP_FRAC_ADD_2(_r, Y, _r);					\
+	    if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
+	      {								\
+		R##_f0--;						\
+		_FP_FRAC_ADD_2(_r, Y, _r);				\
+	      }								\
X 	  }								\
+	if (!_FP_FRAC_EQ_2(_r, _m))					\
+	  R##_f0 |= _FP_WORK_STICKY;					\
X       }									\
-    _FP_FRAC_SUB_2(_r, _r, _m);						\
-									\
-    R##_f1 = _q_f1;							\
-    R##_f0 = _q_f0 | ((_r_f1 | _r_f0) != 0);				\
-    /* adjust so answer is normalized again. I'm not sure what the 	\
-     * final sz param should be. In practice it's never used since      \
-     * N is 1 which is always going to be < _FP_W_TYPE_SIZE...		\
-     */									\
-    /* _FP_FRAC_SRS_2(R,1,_FP_WFRACBITS_##fs);	*/			\
X   } while (0)
X 
X 
@@ -330,17 +402,17 @@
X     if (_FP_FRAC_GT_2(X, Y))						\
X       {									\
X 	R##_e++;							\
-	_x[1] = (X##_f0 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE) |	\
+	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) |	\
X 		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
-			    (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE)));	\
-	_x[2] = X##_f1 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE);		\
+			    (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE)));	\
+	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE);	\
X       }									\
X     else								\
X       {									\
-	_x[1] = (X##_f0 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE) |		\
+	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) |	\
X 		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
-			    (_FP_WFRACBITS - _FP_W_TYPE_SIZE)));	\
-	_x[2] = X##_f1 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE);		\
+			    (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE)));	\
+	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE);	\
X       }									\
X 									\
X     (void) mpn_divrem (_z, 0, _x, 4, _y, 2);				\
@@ -359,33 +431,38 @@
X   do {							\
X     while (q)						\
X       {							\
-        T##_f1 = S##_f1 + q;				\
-        if (T##_f1 <= X##_f1)				\
-          {						\
-            S##_f1 = T##_f1 + q;			\
-            X##_f1 -= T##_f1;				\
-            R##_f1 += q;				\
-          }						\
-        _FP_FRAC_SLL_2(X, 1);				\
-        q >>= 1;					\
+	T##_f1 = S##_f1 + q;				\
+	if (T##_f1 <= X##_f1)				\
+	  {						\
+	    S##_f1 = T##_f1 + q;			\
+	    X##_f1 -= T##_f1;				\
+	    R##_f1 += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
X       }							\
X     q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
-    while (q)						\
+    while (q != _FP_WORK_ROUND)				\
X       {							\
-        T##_f0 = S##_f0 + q;				\
-        T##_f1 = S##_f1;				\
-        if (T##_f1 < X##_f1 || 				\
-            (T##_f1 == X##_f1 && T##_f0 < X##_f0))	\
-          {						\
-            S##_f0 = T##_f0 + q;			\
-            if (((_FP_WS_TYPE)T##_f0) < 0 &&		\
-                ((_FP_WS_TYPE)S##_f0) >= 0)		\
-              S##_f1++;					\
-            _FP_FRAC_SUB_2(X, X, T);			\
-            R##_f0 += q;				\
-          }						\
-        _FP_FRAC_SLL_2(X, 1);				\
-        q >>= 1;					\
+	T##_f0 = S##_f0 + q;				\
+	T##_f1 = S##_f1;				\
+	if (T##_f1 < X##_f1 || 				\
+	    (T##_f1 == X##_f1 && T##_f0 <= X##_f0))	\
+	  {						\
+	    S##_f0 = T##_f0 + q;			\
+	    S##_f1 += (T##_f0 > S##_f0);		\
+	    _FP_FRAC_DEC_2(X, T);			\
+	    R##_f0 += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    if (X##_f0 | X##_f1)				\
+      {							\
+	if (S##_f1 < X##_f1 || 				\
+	    (S##_f1 == X##_f1 && S##_f0 < X##_f0))	\
+	  R##_f0 |= _FP_WORK_ROUND;			\
+	R##_f0 |= _FP_WORK_STICKY;			\
X       }							\
X   } while (0)
X 
@@ -419,8 +496,11 @@
X 
X #define _FP_FRAC_CONV_1_2(dfs, sfs, D, S)				\
X   do {									\
-    _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
-		   _FP_WFRACBITS_##sfs);				\
+    if (S##_c != FP_CLS_NAN)						\
+      _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+		     _FP_WFRACBITS_##sfs);				\
+    else								\
+      _FP_FRAC_SRL_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
X     D##_f = S##_f0;							\
X   } while (0)
X 
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/op-4.h linux/arch/sparc64/math-emu/op-4.h
--- v2.3.3/linux/arch/sparc64/math-emu/op-4.h	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/math-emu/op-4.h	Sat May 29 11:09:04 1999
@@ -1,41 +1,31 @@
-/*
- * Basic four-word fraction declaration and manipulation.
- *
- * When adding quadword support for 32 bit machines, we need
- * to be a little careful as double multiply uses some of these
- * macros: (in op-2.h)
- * _FP_MUL_MEAT_2_wide() uses _FP_FRAC_DECL_4, _FP_FRAC_WORD_4,
- * _FP_FRAC_ADD_4, _FP_FRAC_SRS_4
- * _FP_MUL_MEAT_2_gmp() uses _FP_FRAC_SRS_4 (and should use
- * _FP_FRAC_DECL_4: it appears to be broken and is not used 
- * anywhere anyway. )
- *
- * I've now fixed all the macros that were here from the sparc64 code.
- * [*none* of the shift macros were correct!] -- PMM 02/1998
- * 
- * The only quadword stuff that remains to be coded is: 
- * 1) the conversion to/from ints, which requires 
- * that we check (in op-common.h) that the following do the right thing
- * for quadwords: _FP_TO_INT(Q,4,r,X,rsz,rsg), _FP_FROM_INT(Q,4,X,r,rs,rt)
- * 2) multiply, divide and sqrt, which require:
- * _FP_MUL_MEAT_4_*(R,X,Y), _FP_DIV_MEAT_4_*(R,X,Y), _FP_SQRT_MEAT_4(R,S,T,X,q),
- * This also needs _FP_MUL_MEAT_Q and _FP_DIV_MEAT_Q to be defined to
- * some suitable _FP_MUL_MEAT_4_* macros in sfp-machine.h.
- * [we're free to choose whatever FP_MUL_MEAT_4_* macros we need for
- * these; they are used nowhere else. ]
- */
+/* Software floating-point emulation.
+ Basic four-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (r...@cygnus.com),
+		  Jakub Jelinek (j...@ultra.linux.cz),
+		  David S. Miller (da...@redhat.com) and
+		  Peter Maydell (pmay...@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
X 
X #define _FP_FRAC_DECL_4(X)	_FP_W_TYPE X##_f[4]
X #define _FP_FRAC_COPY_4(D,S)			\
X   (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],	\
X    D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
-/* The _FP_FRAC_SET_n(X,I) macro is intended for use with another
- * macro such as _FP_ZEROFRAC_n which returns n comma separated values.
- * The result is that we get an expansion of __FP_FRAC_SET_n(X,I0,I1,I2,I3)
- * which just assigns the In values to the array X##_f[]. 
- * This is why the number of parameters doesn't appear to match
- * at first glance...      -- PMM 
- */
X #define _FP_FRAC_SET_4(X,I)	__FP_FRAC_SET_4(X, I)
X #define _FP_FRAC_HIGH_4(X)	(X##_f[3])
X #define _FP_FRAC_LOW_4(X)	(X##_f[0])
@@ -47,11 +37,17 @@
X     _skip = (N) / _FP_W_TYPE_SIZE;					\
X     _up = (N) % _FP_W_TYPE_SIZE;					\
X     _down = _FP_W_TYPE_SIZE - _up;					\
-    for (_i = 3; _i > _skip; --_i)					\
-      X##_f[_i] = X##_f[_i-_skip] << _up | X##_f[_i-_skip-1] >> _down;	\
-/* bugfixed: was X##_f[_i] <<= _up;  -- PMM 02/1998 */                  \
-    X##_f[_i] = X##_f[0] << _up; 	                                \
-    for (--_i; _i >= 0; --_i)						\
+    if (!_up)								\
+      for (_i = 3; _i >= _skip; --_i)					\
+	X##_f[_i] = X##_f[_i-_skip];					\
+    else								\
+      {									\
+	for (_i = 3; _i > _skip; --_i)					\
+	  X##_f[_i] = X##_f[_i-_skip] << _up				\
+		      | X##_f[_i-_skip-1] >> _down;			\
+	X##_f[_i--] = X##_f[0] << _up; 					\
+      }									\
+    for (; _i >= 0; --_i)						\
X       X##_f[_i] = 0;							\
X   } while (0)
X 
@@ -62,10 +58,17 @@
X     _skip = (N) / _FP_W_TYPE_SIZE;					\
X     _down = (N) % _FP_W_TYPE_SIZE;					\
X     _up = _FP_W_TYPE_SIZE - _down;					\
-    for (_i = 0; _i < 3-_skip; ++_i)					\
-      X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up;	\
-    X##_f[_i] = X##_f[3] >> _down;			         	\
-    for (++_i; _i < 4; ++_i)						\
+    if (!_down)								\
+      for (_i = 0; _i <= 3-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 3-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[3] >> _down;				\
+      }									\
+    for (; _i < 4; ++_i)						\
X       X##_f[_i] = 0;							\
X   } while (0)
X 
@@ -85,14 +88,21 @@
X     for (_s = _i = 0; _i < _skip; ++_i)					\
X       _s |= X##_f[_i];							\
X     _s |= X##_f[_i] << _up;						\
-/* s is now != 0 if we want to set the LSbit */                         \
-    for (_i = 0; _i < 3-_skip; ++_i)					\
-      X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up;	\
-    X##_f[_i] = X##_f[3] >> _down;					\
-    for (++_i; _i < 4; ++_i)						\
+/* s is now != 0 if we want to set the LSbit */				\
+    if (!_down)								\
+      for (_i = 0; _i <= 3-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 3-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[3] >> _down;				\
+      }									\
+    for (; _i < 4; ++_i)						\
X       X##_f[_i] = 0;							\
-    /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
-    X##_f[0] |= (_s != 0);                                              \
+    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
+    X##_f[0] |= (_s != 0);						\
X   } while (0)
X 
X #define _FP_FRAC_ADD_4(R,X,Y)						\
@@ -100,89 +110,394 @@
X 		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
X 		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
X 
-#define _FP_FRAC_SUB_4(R,X,Y)                                           \
+#define _FP_FRAC_SUB_4(R,X,Y)						\
X   __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
X 		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
X 		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
X 
-#define _FP_FRAC_ADDI_4(X,I)                                            \
+#define _FP_FRAC_DEC_4(X,Y)						\
+  __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
+		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_ADDI_4(X,I)						\
X   __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
X 
X #define _FP_ZEROFRAC_4  0,0,0,0
X #define _FP_MINFRAC_4   0,0,0,1
+#define _FP_MAXFRAC_4	(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
X 
X #define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
X #define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE)X##_f[3] < 0)
-#define _FP_FRAC_OVERP_4(fs,X)  (X##_f[0] & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_OVERP_4(fs,X)  (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
X 
-#define _FP_FRAC_EQ_4(X,Y)                              \
- (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]          \
+#define _FP_FRAC_EQ_4(X,Y)				\
+ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]		\
X   && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
X 
-#define _FP_FRAC_GT_4(X,Y)                              \
- (X##_f[3] > Y##_f[3] ||                                \
-  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||      \
-   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||     \
-    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])       \
-   ))                                                   \
-  ))                                                    \
+#define _FP_FRAC_GT_4(X,Y)				\
+ (X##_f[3] > Y##_f[3] ||				\
+  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
+   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
+    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])	\
+   ))							\
+  ))							\
X  )
X 
-#define _FP_FRAC_GE_4(X,Y)                              \
- (X##_f[3] > Y##_f[3] ||                                \
-  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||      \
-   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||     \
-    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])      \
-   ))                                                   \
-  ))                                                    \
+#define _FP_FRAC_GE_4(X,Y)				\
+ (X##_f[3] > Y##_f[3] ||				\
+  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
+   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
+    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])	\
+   ))							\
+  ))							\
X  )
X 
X 
-#define _FP_FRAC_CLZ_4(R,X)             \
-  do {                                  \
-    if (X##_f[3])                       \
-    {                                   \
-        __FP_CLZ(R,X##_f[3]);           \
-    }                                   \
-    else if (X##_f[2])                  \
-    {                                   \
-        __FP_CLZ(R,X##_f[2]);           \
-        R += _FP_W_TYPE_SIZE;           \
-    }                                   \
-    else if (X##_f[1])                  \
-    {                                   \
-        __FP_CLZ(R,X##_f[2]);           \
-        R += _FP_W_TYPE_SIZE*2;         \
-    }                                   \
-    else                                \
-    {                                   \
-        __FP_CLZ(R,X##_f[0]);           \
-        R += _FP_W_TYPE_SIZE*3;         \
-    }                                   \
+#define _FP_FRAC_CLZ_4(R,X)		\
+  do {					\
+    if (X##_f[3])			\
+    {					\
+	__FP_CLZ(R,X##_f[3]);		\
+    }					\
+    else if (X##_f[2])			\
+    {					\
+	__FP_CLZ(R,X##_f[2]);		\
+	R += _FP_W_TYPE_SIZE;		\
+    }					\
+    else if (X##_f[1])			\
+    {					\
+	__FP_CLZ(R,X##_f[2]);		\
+	R += _FP_W_TYPE_SIZE*2;		\
+    }					\
+    else				\
+    {					\
+	__FP_CLZ(R,X##_f[0]);		\
+	R += _FP_W_TYPE_SIZE*3;		\
+    }					\
X   } while(0)
X 
X 
-#define _FP_UNPACK_RAW_4(fs, X, val)                            \
-  do {                                                          \
-    union _FP_UNION_##fs _flo; _flo.flt = (val);        	\
-    X##_f[0] = _flo.bits.frac0;                                 \
-    X##_f[1] = _flo.bits.frac1;                                 \
-    X##_f[2] = _flo.bits.frac2;                                 \
-    X##_f[3] = _flo.bits.frac3;                                 \
-    X##_e  = _flo.bits.exp;                                     \
-    X##_s  = _flo.bits.sign;                                    \
+#define _FP_UNPACK_RAW_4(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
+    X##_f[0] = _flo.bits.frac0;					\
+    X##_f[1] = _flo.bits.frac1;					\
+    X##_f[2] = _flo.bits.frac2;					\
+    X##_f[3] = _flo.bits.frac3;					\
+    X##_e  = _flo.bits.exp;					\
+    X##_s  = _flo.bits.sign;					\
+  } while (0)
+
+#define _FP_UNPACK_RAW_4_P(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    X##_f[0] = _flo->bits.frac0;				\
+    X##_f[1] = _flo->bits.frac1;				\
+    X##_f[2] = _flo->bits.frac2;				\
+    X##_f[3] = _flo->bits.frac3;				\
+    X##_e  = _flo->bits.exp;					\
+    X##_s  = _flo->bits.sign;					\
X   } while (0)
X 
-#define _FP_PACK_RAW_4(fs, val, X)                              \
-  do {                                                          \
+#define _FP_PACK_RAW_4(fs, val, X)				\
+  do {								\
X     union _FP_UNION_##fs _flo;					\
-    _flo.bits.frac0 = X##_f[0];                                 \
-    _flo.bits.frac1 = X##_f[1];                                 \
-    _flo.bits.frac2 = X##_f[2];                                 \
-    _flo.bits.frac3 = X##_f[3];                                 \
-    _flo.bits.exp   = X##_e;                                    \
-    _flo.bits.sign  = X##_s;                                    \
-    (val) = _flo.flt;                                   	\
+    _flo.bits.frac0 = X##_f[0];					\
+    _flo.bits.frac1 = X##_f[1];					\
+    _flo.bits.frac2 = X##_f[2];					\
+    _flo.bits.frac3 = X##_f[3];					\
+    _flo.bits.exp   = X##_e;					\
+    _flo.bits.sign  = X##_s;					\
+    (val) = _flo.flt;				   		\
+  } while (0)
+
+#define _FP_PACK_RAW_4_P(fs, val, X) \
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    _flo->bits.frac0 = X##_f[0];				\
+    _flo->bits.frac1 = X##_f[1];				\
+    _flo->bits.frac2 = X##_f[2];				\
+    _flo->bits.frac3 = X##_f[3];				\
+    _flo->bits.exp   = X##_e;					\
+    _flo->bits.sign  = X##_s;					\
+  } while (0)
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
+
+#define _FP_MUL_MEAT_4_wide(fs, R, X, Y, doit)				    \
+  do {									    \
+    _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	    \
+    _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f);	    \
+									    \
+    doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
+    doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]);				    \
+    doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]);				    \
+    doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]);				    \
+    doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]);				    \
+    doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]);				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0,		    \
+		    0,0,_FP_FRAC_WORD_8(_z,1));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0,		    \
+		    _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0,		    \
+		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0,		    \
+		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2));				    \
+    doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]);				    \
+    doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]);				    \
+    doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]);				    \
+    doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]);				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0,		    \
+		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0,		    \
+		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0,		    \
+		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3));				    \
+    doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]);				    \
+    doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]);				    \
+    doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]);				    \
+    doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]);				    \
+    doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]);				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0,		    \
+		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0,		    \
+		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0,		    \
+		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _FP_FRAC_WORD_8(_z,5));				    \
+    doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]);				    \
+    __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _b_f1,_b_f0,					    \
+		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6));	    \
+									    \
+    /* Normalize since we know where the msb of the multiplicands	    \
+       were (bit B), we know that the msb of the of the product is	    \
+       at either 2B or 2B-1.  */					    \
+    _FP_FRAC_SRS_8(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);	    \
+    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
+  } while (0)
+
+#define _FP_MUL_MEAT_4_gmp(fs, R, X, Y)					    \
+  do {									    \
+    _FP_FRAC_DECL_8(_z);						    \
+									    \
+    mpn_mul_n(_z_f, _x_f, _y_f, 4);					    \
+									    \
+    /* Normalize since we know where the msb of the multiplicands	    \
+       were (bit B), we know that the msb of the of the product is	    \
+       at either 2B or 2B-1.  */					    \
+    _FP_FRAC_SRS_8(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);	    \
+    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
+  } while (0)
+
+/*
+ * Helper utility for _FP_DIV_MEAT_4_udiv:
+ * pppp = m * nnn
+ */
+#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0)				    \
+  do {									    \
+    UWtype _t;								    \
+    umul_ppmm(p1,p0,m,n0);						    \
+    umul_ppmm(p2,_t,m,n1);						    \
+    __FP_FRAC_ADDI_2(p2,p1,_t);						    \
+    umul_ppmm(p3,_t,m,n2);						    \
+    __FP_FRAC_ADDI_2(p3,p2,_t);						    \
+  } while (0)
+
+/*
+ * Division algorithms:
+ */
+
+#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y)				    \
+  do {									    \
+    int _i;								    \
+    _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m);				    \
+    _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4);					    \
+    if (_FP_FRAC_GT_4(X, Y))						    \
+      {									    \
+	_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1);			    \
+	_FP_FRAC_SRL_4(X, 1);						    \
+      }									    \
+    else								    \
+      R##_e--;								    \
+									    \
+    /* Normalize, i.e. make the most significant bit of the 		    \
+       denominator set. */						    \
+    _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs);				    \
+									    \
+    for (_i = 3; ; _i--)						    \
+      {									    \
+        if (X##_f[3] == Y##_f[3])					    \
+          {								    \
+            /* This is a special case, not an optimization		    \
+               (X##_f[3]/Y##_f[3] would not fit into UWtype).		    \
+               As X## is guaranteed to be < Y,  R##_f[_i] can be either	    \
+               (UWtype)-1 or (UWtype)-2.  */				    \
+            R##_f[_i] = -1;						    \
+            if (!_i)							    \
+	      break;							    \
+            __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],	    \
+			    Y##_f[2], Y##_f[1], Y##_f[0], 0,		    \
+			    X##_f[2], X##_f[1], X##_f[0], _n_f[_i]);	    \
+            _FP_FRAC_SUB_4(X, Y, X);					    \
+            if (X##_f[3] > Y##_f[3])					    \
+              {								    \
+                R##_f[_i] = -2;						    \
+                _FP_FRAC_ADD_4(X, Y, X);				    \
+              }								    \
+          }								    \
+        else								    \
+          {								    \
+            udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]);  \
+            umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0],		    \
+			  R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]);	    \
+            X##_f[2] = X##_f[1];					    \
+            X##_f[1] = X##_f[0];					    \
+            X##_f[0] = _n_f[_i];					    \
+            if (_FP_FRAC_GT_4(_m, X))					    \
+              {								    \
+                R##_f[_i]--;						    \
+                _FP_FRAC_ADD_4(X, Y, X);				    \
+                if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X))	    \
+                  {							    \
+		    R##_f[_i]--;					    \
+		    _FP_FRAC_ADD_4(X, Y, X);				    \
+                  }							    \
+              }								    \
+            _FP_FRAC_DEC_4(X, _m);					    \
+            if (!_i)							    \
+	      {								    \
+		if (!_FP_FRAC_EQ_4(X, _m))				    \
+		  R##_f[0] |= _FP_WORK_STICKY;				    \
+		break;							    \
+	      }								    \
+          }								    \
+      }									    \
+  } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+ 
+#define _FP_SQRT_MEAT_4(R, S, T, X, q)				\
+  do {								\
+    while (q)							\
+      {								\
+	T##_f[3] = S##_f[3] + q;				\
+	if (T##_f[3] <= X##_f[3])				\
+	  {							\
+	    S##_f[3] = T##_f[3] + q;				\
+	    X##_f[3] -= T##_f[3];				\
+	    R##_f[3] += q;					\
+	  }							\
+	_FP_FRAC_SLL_4(X, 1);					\
+	q >>= 1;						\
+      }								\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
+    while (q)							\
+      {								\
+	T##_f[2] = S##_f[2] + q;				\
+	T##_f[3] = S##_f[3];					\
+	if (T##_f[3] < X##_f[3] || 				\
+	    (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2]))	\
+	  {							\
+	    S##_f[2] = T##_f[2] + q;				\
+	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
+	    __FP_FRAC_DEC_2(X##_f[3], X##_f[2],			\
+			    T##_f[3], T##_f[2]);		\
+	    R##_f[2] += q;					\
+	  }							\
+	_FP_FRAC_SLL_4(X, 1);					\
+	q >>= 1;						\
+      }								\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
+    while (q)							\
+      {								\
+	T##_f[1] = S##_f[1] + q;				\
+	T##_f[2] = S##_f[2];					\
+	T##_f[3] = S##_f[3];					\
+	if (T##_f[3] < X##_f[3] || 				\
+	    (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] ||	\
+	     (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1]))))	\
+	  {							\
+	    S##_f[1] = T##_f[1] + q;				\
+	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
+	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
+	    __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1],	\
+	    		    T##_f[3], T##_f[2], T##_f[1]);	\
+	    R##_f[1] += q;					\
+	  }							\
+ _FP_FRAC_SLL_4(X, 1); \
+	q >>= 1;						\
+      }								\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
+ while (q != _FP_WORK_ROUND) \
+      {								\
+	T##_f[0] = S##_f[0] + q;				\
+	T##_f[1] = S##_f[1];					\
+	T##_f[2] = S##_f[2];					\
+	T##_f[3] = S##_f[3];					\
+	if (_FP_FRAC_GE_4(X,T))					\
+	  {							\
+	    S##_f[0] = T##_f[0] + q;				\
+	    S##_f[1] += (T##_f[0] > S##_f[0]);			\
+	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
+	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
+	    _FP_FRAC_DEC_4(X, T);				\
+	    R##_f[0] += q;					\
+	  }							\
+ _FP_FRAC_SLL_4(X, 1); \
+	q >>= 1;						\
+      }								\
+    if (!_FP_FRAC_ZEROP_4(X))					\
+      {								\
+	if (_FP_FRAC_GT_4(X,S))					\
+	  R##_f[0] |= _FP_WORK_ROUND;				\
+	R##_f[0] |= _FP_WORK_STICKY;				\
+      }								\
X   } while (0)
X 
X 
@@ -193,6 +508,13 @@
X #define __FP_FRAC_SET_4(X,I3,I2,I1,I0)					\
X   (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
X 
+#ifndef __FP_FRAC_ADD_3
+#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  (r0 = x0 + y0,							\
+   r1 = x1 + y1 + (r0 < x0),						\
+   r2 = x2 + y2 + (r1 < x1))
+#endif
+
X #ifndef __FP_FRAC_ADD_4
X #define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
X   (r0 = x0 + y0,							\
@@ -201,18 +523,56 @@
X    r3 = x3 + y3 + (r2 < x2))
X #endif
X 
+#ifndef __FP_FRAC_SUB_3
+#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  (r0 = x0 - y0,							\
+   r1 = x1 - y1 - (r0 > x0),						\
+   r2 = x2 - y2 - (r1 > x1))
+#endif
+
X #ifndef __FP_FRAC_SUB_4
X #define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  (r0 = x0 - y0,                                                        \
-   r1 = x1 - y1 - (r0 > x0),                                            \
-   r2 = x2 - y2 - (r1 > x1),                                            \
+  (r0 = x0 - y0,							\
+   r1 = x1 - y1 - (r0 > x0),						\
+   r2 = x2 - y2 - (r1 > x1),						\
X    r3 = x3 - y3 - (r2 > x2))
X #endif
X 
+#ifndef __FP_FRAC_DEC_3
+#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0)				\
+  do {									\
+    UWtype _t0, _t1;							\
+    _t0 = x0;								\
+    x0 -= y0;								\
+    _t1 = x1;								\
+    x1 -= y1 + (x0 > _t0);						\
+    x2 -= y2 + (x1 > _t1);						\
+  } while (0)
+#endif
+
+#ifndef __FP_FRAC_DEC_4
+#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0)			\
+  do {									\
+    UWtype _t0, _t1;							\
+    _t0 = x0;								\
+    x0 -= y0;								\
+    _t1 = x1;								\
+    x1 -= y1 + (x0 > _t0);						\
+    _t0 = x2;								\
+    x2 -= y2 + (x1 > _t1);						\
+    x3 -= y3 + (x2 > _t0);						\
+  } while (0)
+#endif
+
X #ifndef __FP_FRAC_ADDI_4
-/* I always wanted to be a lisp programmer :-> */
-#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)                                 \
-  (x3 += ((x2 += ((x1 += ((x0 += i) < x0)) < x1) < x2)))
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
+  do {									\
+    UWtype _t;								\
+    _t = ((x0 += i) < i);						\
+    x1 += _t; _t = (x1 < _t);						\
+    x2 += _t; _t = (x2 < _t);						\
+    x3 += _t;								\
+  } while (0)
X #endif
X 
X /* Convert FP values between word sizes. This appears to be more
@@ -222,47 +582,53 @@
X  * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
X  * the ones in op-2.h and op-1.h. 
X  */
-#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
-                        _FP_WFRACBITS_##sfs);                           \
-     D##_f = S##_f[0];                                                   \
+#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S)				\
+   do {									\
+     if (S##_c != FP_CLS_NAN)						\
+       _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+			  _FP_WFRACBITS_##sfs);				\
+     else								\
+       _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
+     D##_f = S##_f[0];							\
X   } while (0)
X 
-#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
-                        _FP_WFRACBITS_##sfs);                           \
-     D##_f0 = S##_f[0];                                                  \
-     D##_f1 = S##_f[1];                                                  \
+#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S)				\
+   do {									\
+     if (S##_c != FP_CLS_NAN)						\
+       _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+		      _FP_WFRACBITS_##sfs);				\
+     else								\
+       _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
+     D##_f0 = S##_f[0];							\
+     D##_f1 = S##_f[1];							\
X   } while (0)
X 
X /* Assembly/disassembly for converting to/from integral types.  
X  * No shifting or overflow handled here.
X  */
X /* Put the FP value X into r, which is an integer of size rsize. */
-#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)                                \
-  do {                                                                  \
-    if (rsize <= _FP_W_TYPE_SIZE)                                       \
-      r = X##_f[0];                                                     \
-    else if (rsize <= 2*_FP_W_TYPE_SIZE)                                \
-    {                                                                   \
-      r = X##_f[1];                                                     \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[0];                                                    \
-    }                                                                   \
-    else                                                                \
-    {                                                                   \
-      /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
-      /* and int == 4words as a single case.                         */ \
-      r = X##_f[3];                                                     \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[2];                                                    \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[1];                                                    \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[0];                                                    \
-    }                                                                   \
+#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)				\
+  do {									\
+    if (rsize <= _FP_W_TYPE_SIZE)					\
+      r = X##_f[0];							\
+    else if (rsize <= 2*_FP_W_TYPE_SIZE)				\
+    {									\
+      r = X##_f[1];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[0];							\
+    }									\
+    else								\
+    {									\
+      /* I'm feeling lazy so we deal with int == 3words (implausible)*/	\
+      /* and int == 4words as a single case.			 */	\
+      r = X##_f[3];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[2];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[1];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[0];							\
+    }									\
X   } while (0)
X 
X /* "No disassemble Number Five!" */
@@ -270,28 +636,26 @@
X  * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
X  * having to mask the values we store into it.
X  */
-#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)                             \
-  do {                                                                  \
-    X##_f[0] = r;                                                       \
-    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);   \
+#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)				\
+  do {									\
+    X##_f[0] = r;							\
+    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
X     X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
X     X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
X   } while (0);
X 
-#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     D##_f[0] = S##_f;                                                  \
-     D##_f[1] = D##_f[2] = D##_f[3] = 0;                                \
-     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
+#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)				\
+   do {									\
+     D##_f[0] = S##_f;							\
+     D##_f[1] = D##_f[2] = D##_f[3] = 0;				\
+     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
X    } while (0)
X 
-#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     D##_f[0] = S##_f0;                                                 \
-     D##_f[1] = S##_f1;                                                 \
-     D##_f[2] = D##_f[3] = 0;                                           \
-     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
+#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S)				\
+   do {									\
+     D##_f[0] = S##_f0;							\
+     D##_f[1] = S##_f1;							\
+     D##_f[2] = D##_f[3] = 0;						\
+     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
X    } while (0)
X 
-/* FIXME! This has to be written */
-#define _FP_SQRT_MEAT_4(R, S, T, X, q)
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/op-8.h linux/arch/sparc64/math-emu/op-8.h
--- v2.3.3/linux/arch/sparc64/math-emu/op-8.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/math-emu/op-8.h	Sat May 29 11:09:04 1999
@@ -0,0 +1,103 @@
+/* Software floating-point emulation.
+   Basic eight-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (r...@cygnus.com),
+ Jakub Jelinek (j...@ultra.linux.cz) and
+		  Peter Maydell (pmay...@chiark.greenend.org.uk).
+                                                         
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* We need just a few things from here for op-4, if we ever need some
+   other macros, they can be added. */
+#define _FP_FRAC_DECL_8(X)	_FP_W_TYPE X##_f[8]
+#define _FP_FRAC_HIGH_8(X)	(X##_f[7])
+#define _FP_FRAC_LOW_8(X)	(X##_f[0])
+#define _FP_FRAC_WORD_8(X,w)	(X##_f[w])
+
+#define _FP_FRAC_SLL_8(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _up = (N) % _FP_W_TYPE_SIZE;					\
+    _down = _FP_W_TYPE_SIZE - _up;					\
+    if (!_up)								\
+      for (_i = 7; _i >= _skip; --_i)					\
+	X##_f[_i] = X##_f[_i-_skip];					\
+    else								\
+      {									\
+	for (_i = 7; _i > _skip; --_i)					\
+	  X##_f[_i] = X##_f[_i-_skip] << _up				\
+		      | X##_f[_i-_skip-1] >> _down;			\
+	X##_f[_i--] = X##_f[0] << _up; 					\
+      }									\
+    for (; _i >= 0; --_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+#define _FP_FRAC_SRL_8(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    if (!_down)								\
+      for (_i = 0; _i <= 7-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 7-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[7] >> _down;				\
+      }									\
+    for (; _i < 8; ++_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+
+/* Right shift with sticky-lsb. 
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRS_8(X,N,size)					\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _FP_W_TYPE _s;							\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    for (_s = _i = 0; _i < _skip; ++_i)					\
+      _s |= X##_f[_i];							\
+    _s |= X##_f[_i] << _up;						\
+/* s is now != 0 if we want to set the LSbit */				\
+    if (!_down)								\
+      for (_i = 0; _i <= 7-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 7-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[7] >> _down;				\
+      }									\
+    for (; _i < 8; ++_i)						\
+      X##_f[_i] = 0;							\
+    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
+    X##_f[0] |= (_s != 0);						\
+  } while (0)
+
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/op-common.h linux/arch/sparc64/math-emu/op-common.h
--- v2.3.3/linux/arch/sparc64/math-emu/op-common.h	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/math-emu/op-common.h	Sat May 29 11:09:04 1999
@@ -1,3 +1,25 @@
+/* Software floating-point emulation. Common operations.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (r...@cygnus.com),
+		  Jakub Jelinek (j...@ultra.linux.cz),
+		  David S. Miller (da...@redhat.com) and
+		  Peter Maydell (pmay...@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
X 
X #define _FP_DECL(wc, X)			\
X   _FP_I_TYPE X##_c, X##_s, X##_e;	\
@@ -13,7 +35,7 @@
X   switch (X##_e)							\
X   {									\
X   default:								\
-    _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs;				\
+    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;			\
X     _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);					\
X     X##_e -= _FP_EXPBIAS_##fs;						\
X     X##_c = FP_CLS_NORMAL;						\
@@ -31,6 +53,7 @@
X 	_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));			\
X 	X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;				\
X 	X##_c = FP_CLS_NORMAL;						\
+	FP_SET_EXCEPTION(FP_EX_DENORM);					\
X       }									\
X     break;								\
X 									\
@@ -38,13 +61,16 @@
X     if (_FP_FRAC_ZEROP_##wc(X))						\
X       X##_c = FP_CLS_INF;						\
X     else								\
-      /* we don't differentiate between signaling and quiet nans */	\
-      X##_c = FP_CLS_NAN;						\
+      {									\
+	X##_c = FP_CLS_NAN;						\
+	/* Check for signaling NaN */					\
+	if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))		\
+	  FP_SET_EXCEPTION(FP_EX_INVALID);				\
+      }									\
X     break;								\
X   }									\
X } while (0)
X 
-
X /*
X  * Before packing the bits back into the native fp result, take care
X  * of such mundane things as rounding and overflow.  Also, for some
@@ -53,14 +79,14 @@
X  */
X 
X #define _FP_PACK_CANONICAL(fs, wc, X)				\
-({int __ret = 0;						\
+do {								\
X   switch (X##_c)						\
X   {								\
X   case FP_CLS_NORMAL:						\
X     X##_e += _FP_EXPBIAS_##fs;					\
X     if (X##_e > 0)						\
X       {								\
-	__ret |= _FP_ROUND(wc, X);				\
+	_FP_ROUND(wc, X);					\
X 	if (_FP_FRAC_OVERP_##wc(fs, X))				\
X 	  {							\
X 	    _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1));		\
@@ -70,10 +96,33 @@
X 	  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);			\
X 	if (X##_e >= _FP_EXPMAX_##fs)				\
X 	  {							\
-	    /* overflow to infinity */				\
-	    X##_e = _FP_EXPMAX_##fs;				\
-	    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);		\
-            __ret |= EFLAG_OVERFLOW;				\
+	    /* overflow */					\
+	    switch (FP_ROUNDMODE)				\
+	      {							\
+	      case FP_RND_NEAREST:				\
+		X##_c = FP_CLS_INF;				\
+		break;						\
+	      case FP_RND_PINF:					\
+		if (!X##_s) X##_c = FP_CLS_INF;			\
+		break;						\
+	      case FP_RND_MINF:					\
+		if (X##_s) X##_c = FP_CLS_INF;			\
+		break;						\
+	      }							\
+	    if (X##_c == FP_CLS_INF)				\
+	      {							\
+		/* Overflow to infinity */			\
+		X##_e = _FP_EXPMAX_##fs;			\
+		_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
+	      }							\
+	    else						\
+	      {							\
+		/* Overflow to maximum normal */		\
+		X##_e = _FP_EXPMAX_##fs - 1;			\
+		_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);		\
+	      }							\
+	    FP_SET_EXCEPTION(FP_EX_OVERFLOW);			\
+            FP_SET_EXCEPTION(FP_EX_INEXACT);			\
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 09'
echo 'File patch-2.3.4 is continued in part 10'
echo 10 > _shar_seq_.tmp
#!/bin/sh
# this is part 12 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X {
X 	switch (cardtype) {
X 		default:
-		case AVM_CARDTYPE_B1: return "B1";
-		case AVM_CARDTYPE_M1: return "M1";
-		case AVM_CARDTYPE_M2: return "M2";
-		case AVM_CARDTYPE_T1: return "T1";
+		case AVM_CARDTYPE_B1:    return "B1-ISA";
+		case AVM_CARDTYPE_B1PCI: return "B1-PCI";
+		case AVM_CARDTYPE_M1:    return "M1";
+		case AVM_CARDTYPE_M2:    return "M2";
+		case AVM_CARDTYPE_T1:    return "T1";
X 	}
X }
X 
@@ -300,7 +339,7 @@
X 			}
X 		}
X 		APPL(appl)->releasing--;
-		if (APPL(appl)->releasing == 0) {
+		if (APPL(appl)->releasing <= 0) {
X 	                APPL(appl)->signal = 0;
X 			APPL_MARK_FREE(appl);
X 			printk(KERN_INFO "b1capi: appl %d down\n", appl);
@@ -433,6 +472,7 @@
X 
X /* -------- card ready callback ------------------------------- */
X 
+
X void avmb1_card_ready(avmb1_card * card)
X {
X         struct capi_profile *profp =
@@ -441,6 +481,7 @@
X 	__u16 appl;
X 	char *cardname, cname[20];
X 	__u32 flag;
+        int nbchan = profp->nbchannel;
X 
X 	card->cversion.majorversion = 2;
X 	card->cversion.minorversion = 0;
@@ -453,9 +494,14 @@
X 
X 	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
X 		if (VALID_APPLID(appl) && !APPL(appl)->releasing) {
+			int nconn, want = APPL(appl)->rparam.level3cnt;
+
+			if (want > 0) nconn = want;
+			else nconn = nbchan * -want;
+			if (nconn == 0) nconn = nbchan;
+
X 			B1_send_register(card->port, appl,
-				1024 * (APPL(appl)->rparam.level3cnt+1),
-				APPL(appl)->rparam.level3cnt,
+				1024 * (nconn+1), nconn,
X 				APPL(appl)->rparam.datablkcnt,
X 				APPL(appl)->rparam.datablklen);
X 		}
@@ -553,8 +599,8 @@
X 				 SA_SHIRQ, card->name, card)) != 0) {
X 		printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n",
X 		       irq, irqval);
-		release_region((unsigned short) port, AVMB1_PORTLEN);
-		return -EIO;
+		release_region(port, AVMB1_PORTLEN);
+		return -EBUSY;
X 	}
X 
X 	card->cardstate = CARD_DETECTED;
@@ -578,8 +624,14 @@
X 	if (!B1_valid_irq(irq, cardtype)) {
X 		printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n",
X 				irq, cardtype2str(cardtype));
-		return -EIO;
+		return -EINVAL;
+	}
+	if (!B1_valid_port(port, cardtype)) {
+		printk(KERN_WARNING "b1capi: port 0x%x not valid for %s-card.\n",
+				port, cardtype2str(cardtype));
+		return -EINVAL;
X 	}
+	B1_reset(port);
X 	if ((rc = B1_detect(port, cardtype)) != 0) {
X 		printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n",
X 					  cardtype2str(cardtype), port, rc);
@@ -591,10 +643,10 @@
X 	   	case AVM_CARDTYPE_M1:
X 	   	case AVM_CARDTYPE_M2:
X 	   	case AVM_CARDTYPE_B1:
+	   	case AVM_CARDTYPE_B1PCI:
X 	    		printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port);
X 			break;
X 	   	case AVM_CARDTYPE_T1:
-	    		printk(KERN_NOTICE "b1capi: AVM-%s-Controller may be at 0x%x\n", cardtype2str(cardtype), port);
X 			break;
X 	}
X 
@@ -603,11 +655,11 @@
X 
X int avmb1_probecard(int port, int irq, int cardtype)
X {
-	if (check_region((unsigned short) port, AVMB1_PORTLEN)) {
+	if (check_region(port, AVMB1_PORTLEN)) {
X 		printk(KERN_WARNING
X 		       "b1capi: ports 0x%03x-0x%03x in use.\n",
X 		       port, port + AVMB1_PORTLEN);
-		return -EIO;
+		return -EBUSY;
X 	}
X         return avmb1_detectcard(port, irq, cardtype);
X }
@@ -618,11 +670,16 @@
X    	if (!VALID_CARD(cnr)) 
X 		return -ESRCH;
X 	card = CARD(cnr);
+
X 	if (card->cardstate == CARD_FREE)
X 		return -ESRCH;
X 	if (card->cardstate == CARD_RUNNING)
X 		avmb1_card_down(card, freeio);
X 
+	if (card->cardstate != CARD_FREE)
+		if (card->cardtype == AVM_CARDTYPE_T1)
+			T1_reset(card->port);
+
X 	free_irq(card->irq, card);
X 	if (freeio)
X 		release_region(card->port, AVMB1_PORTLEN);
@@ -667,6 +724,7 @@
X 
X static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
X {
+	int nconn, want = rparam->level3cnt;
X 	int i;
X 	int appl;
X 
@@ -686,13 +744,20 @@
X 	memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
X 
X 	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		struct capi_profile *profp =
+			(struct capi_profile *)cards[i].version[VER_PROFILE];
+
X 		if (cards[i].cardstate != CARD_RUNNING)
X 			continue;
+
+		if (want > 0) nconn = want;
+		else nconn = profp->nbchannel * -want;
+		if (nconn == 0) nconn = profp->nbchannel;
+
X 		B1_send_register(cards[i].port, appl,
-			       1024 * (APPL(appl)->rparam.level3cnt + 1),
-				 APPL(appl)->rparam.level3cnt,
-				 APPL(appl)->rparam.datablkcnt,
-				 APPL(appl)->rparam.datablklen);
+			1024 * (nconn+1), nconn,
+			APPL(appl)->rparam.datablkcnt,
+			APPL(appl)->rparam.datablklen);
X 	}
X 	*applidp = appl;
X 	printk(KERN_INFO "b1capi: appl %d up\n", appl);
@@ -705,8 +770,6 @@
X 	struct sk_buff *skb;
X 	int i;
X 
-	if (ncards == 0)
-		return CAPI_REGNOTINSTALLED;
X 	if (!VALID_APPLID(applid) || APPL(applid)->releasing)
X 		return CAPI_ILLAPPNR;
X 	while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
@@ -718,7 +781,7 @@
X 		APPL(applid)->releasing++;
X 		B1_send_release(cards[i].port, applid);
X 	}
-	if (APPL(applid)->releasing == 0) {
+	if (APPL(applid)->releasing <= 0) {
X 	        APPL(applid)->signal = 0;
X 		APPL_MARK_FREE(applid);
X 		printk(KERN_INFO "b1capi: appl %d down\n", applid);
@@ -863,7 +926,43 @@
X 		if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0)
X 			return rc;
X 
-		return avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
+                if (cdef.cardtype == AVM_CARDTYPE_T1) {
+			int i;
+		        for (i=0; i < CAPI_MAXCONTR; i++) {
+	        	    	if (   cards[i].cardstate != CARD_FREE
+				    && cards[i].cardtype == AVM_CARDTYPE_T1
+				    && cards[i].cardnr == cdef.cardnr) {
+					printk(KERN_ERR
+						"b1capi: T1-HEMA-card-%d already at 0x%x\n",
+						cdef.cardnr, cards[i].port);
+					return -EBUSY;
+				}
+                        }
+			rc = T1_detectandinit(cdef.port,cdef.irq,cdef.cardnr);
+			if (rc) {
+			        printk(KERN_NOTICE "b1capi: NO T1-HEMA-card-%d at 0x%x (%d)\n",
+					  cdef.cardnr, cdef.port, rc);
+				return -EIO;
+                        }
+			printk(KERN_NOTICE "b1capi: T1-HEMA-card-%d at 0x%x\n",
+				  cdef.cardnr, cdef.port);
+		}
+
+		rc = avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
+		if (rc < 0)
+			return rc;
+		/* don't want to change interface t
+		   addcard/probecard/registercard */
+                if (cdef.cardtype == AVM_CARDTYPE_T1) {
+			int i;
+		        for (i=0; i < CAPI_MAXCONTR; i++) {
+	        	    	if (cards[i].cnr == rc) {
+					cards[i].cardnr = cdef.cardnr;
+					break;
+				}
+                        }
+		}
+		return rc;
X 
X 	case AVMB1_LOAD:
X 	case AVMB1_LOAD_AND_CONFIG:
@@ -883,8 +982,7 @@
X 			return -ESRCH;
X 
X 		if (ldef.t4file.len <= 0) {
-			if (loaddebug)
-				printk(KERN_DEBUG "b1capi: load: invalid parameter length of t4file is %d ?\n", ldef.t4file.len);
+			printk(KERN_DEBUG "b1capi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
X 			return -EINVAL;
X 		}
X 
@@ -906,12 +1004,19 @@
X 		}
X 
X 		B1_reset(card->port);
+
+		if (loaddebug) {
+			printk(KERN_DEBUG "b1capi: loading contr %d\n",
+				ldef.contr);
+		}
+
X 		if ((rc = B1_load_t4file(card->port, &ldef.t4file))) {
X 			B1_reset(card->port);
X 			printk(KERN_ERR "b1capi: failed to load t4file!!\n");
X 			card->cardstate = CARD_DETECTED;
X 			return rc;
X 		}
+
X 		B1_disable_irq(card->port);
X 
X 		if (ldef.t4config.len > 0) { /* load config */
@@ -944,8 +1049,7 @@
X 		card->cardstate = CARD_INITSTATE;
X 		save_flags(flags);
X 		cli();
-		B1_assign_irq(card->port, card->irq, card->cardtype);
-		B1_enable_irq(card->port);
+		B1_setinterrupt(card->port, card->irq, card->cardtype);
X 		restore_flags(flags);
X 
X 		if (loaddebug) {
@@ -956,7 +1060,14 @@
X 		/*
X 		 * init card
X 		 */
-		B1_send_init(card->port, AVM_NAPPS, AVM_NNCCI, card->cnr - 1);
+                if (card->cardtype == AVM_CARDTYPE_T1)
+		   B1_send_init(card->port, AVM_NAPPS,
+					    AVM_NNCCI_PER_CHANNEL*30,
+				   	    card->cnr - 1);
+		else
+		   B1_send_init(card->port, AVM_NAPPS,
+					    AVM_NNCCI_PER_CHANNEL*2,
+				   	    card->cnr - 1);
X 
X 		if (loaddebug) {
X 			printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n",
@@ -998,6 +1109,19 @@
X 			return rc;
X 
X 		return 0;
+	case AVMB1_REMOVECARD:
+		if ((rc = copy_from_user((void *) &rdef, data,
+					 sizeof(avmb1_resetdef))))
+			return rc;
+		if (!VALID_CARD(rdef.contr))
+			return -ESRCH;
+
+		card = CARD(rdef.contr);
+
+		if (card->cardstate != CARD_DETECTED)
+			return -EBUSY;
+
+		return avmb1_unregistercard(rdef.contr, 1);
X 	}
X 	return -EINVAL;
X }
@@ -1035,6 +1159,7 @@
X 	userp->next = capi_users;
X 	capi_users = userp;
X 	MOD_INC_USE_COUNT;
+	printk(KERN_NOTICE "b1capi: %s attached\n", userp->name);
X 
X 	return &avmb1_interface;
X }
@@ -1048,6 +1173,7 @@
X 			*pp = userp->next;
X 			userp->next = 0;
X 			MOD_DEC_USE_COUNT;
+			printk(KERN_NOTICE "b1capi: %s detached\n", userp->name);
X 			return 0;
X 		}
X 	}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/b1lli.c linux/drivers/isdn/avmb1/b1lli.c
--- v2.3.3/linux/drivers/isdn/avmb1/b1lli.c	Wed Dec 23 09:44:41 1998
+++ linux/drivers/isdn/avmb1/b1lli.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,46 @@
X /*
- * $Id: b1lli.c,v 1.6 1998/02/13 07:09:11 calle Exp $
+ * $Id: b1lli.c,v 1.10 1999/04/15 19:49:31 calle Exp $
X  * 
X  * ISDN lowlevel-module for AVM B1-card.
X  * 
X  * (c) Copyright 1997 by Carsten Paeth (ca...@calle.in-berlin.de)
X  * 
X  * $Log: b1lli.c,v $
+ * Revision 1.10  1999/04/15 19:49:31  calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.9  1999/01/05 18:33:23  he
+ * merged remaining 2.2pre{1,2} changes (jiffies and Config)
+ *
+ * Revision 1.8  1998/10/25 14:39:00  fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.7  1998/03/29 16:06:00  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.10  1998/03/20 20:34:41  calle
+ * port valid check now only for T1, because of the PCI and PCMCIA cards.
+ *
+ * Revision 1.1.2.9  1998/03/20 14:38:20  calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.1.2.8  1998/03/18 17:43:29  calle
+ * T1 with fastlink, bugfix for multicontroller support in capidrv.c
+ *
+ * Revision 1.1.2.7  1998/03/04 17:33:50  calle
+ * Changes for T1.
+ *
+ * Revision 1.1.2.6  1998/02/27 15:40:44  calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
+ * Revision 1.1.2.5  1998/02/13 16:28:28  calle
+ * first step for T1
+ *
X  * Revision 1.6  1998/02/13 07:09:11  calle
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -41,6 +76,7 @@
X  *
X  * 
X  */
+/* #define FASTLINK_DEBUG */
X 
X #include <linux/kernel.h>
X #include <linux/skbuff.h>
@@ -55,6 +91,8 @@
X #include "capicmd.h"
X #include "capiutil.h"
X 
+extern int showcapimsgs;
+
X /*
X  * LLI Messages to the ISDN-ControllerISDN Controller 
X  */
@@ -93,6 +131,8 @@
X #define SEND_CONFIG		0x21    /*
X                                          */
X 
+#define SEND_POLLACK		0x73    /* T1 Watchdog */
+
X /*
X  * LLI Messages from the ISDN-ControllerISDN Controller 
X  */
@@ -136,6 +176,10 @@
X #define RECEIVE_RELEASE		0x26	/*
X 					   * int32 AppllID int32 0xffffffff 
X 					 */
+#define RECEIVE_TASK_READY	0x31	/*
+					   * int32 tasknr
+					   * int32 Length Taskname ...
+					 */
X 
X #define WRITE_REGISTER		0x00
X #define READ_REGISTER		0x01
@@ -150,14 +194,48 @@
X #define B1_OUTSTAT		0x03
X #define B1_RESET		0x10
X #define B1_ANALYSE		0x04
-#define B1_IDENT		0x17  /* Hema card T1 */
-#define B1_IRQ_MASTER		0x12  /* Hema card T1 */
+
+/* Hema card T1 */
+
+#define T1_FASTLINK		0x00
+#define T1_SLOWLINK		0x08
+
+#define T1_READ			B1_READ
+#define T1_WRITE		B1_WRITE
+#define T1_INSTAT		B1_INSTAT
+#define T1_OUTSTAT		B1_OUTSTAT
+#define T1_IRQENABLE		0x05
+#define T1_FIFOSTAT		0x06
+#define T1_RESETLINK		0x10
+#define T1_ANALYSE		0x11
+#define T1_IRQMASTER		0x12
+#define T1_IDENT		0x17
+#define T1_RESETBOARD		0x1f
+
+#define	T1F_IREADY		0x01
+#define	T1F_IHALF		0x02
+#define	T1F_IFULL		0x04
+#define	T1F_IEMPTY		0x08
+#define	T1F_IFLAGS		0xF0
+
+#define	T1F_OREADY		0x10
+#define	T1F_OHALF		0x20
+#define	T1F_OEMPTY		0x40
+#define	T1F_OFULL		0x80
+#define	T1F_OFLAGS		0xF0
+
+/* there are HEMA cards with 1k and 4k FIFO out */
+#define FIFO_OUTBSIZE		256
+#define FIFO_INPBSIZE		512
+
+#define HEMA_VERSION_ID		0
+#define HEMA_PAL_ID		0
X 
X #define B1_STAT0(cardtype)  ((cardtype) == AVM_CARDTYPE_M1 ? 0x81200000l : 0x80A00000l)
X #define B1_STAT1(cardtype)  (0x80E00000l)
X 
X 
-static inline unsigned char b1outp(unsigned short base,
+static inline unsigned char b1outp(unsigned int base,
X 				   unsigned short offset,
X 				   unsigned char value)
X {
@@ -165,22 +243,44 @@
X 	return inb(base + B1_ANALYSE);
X }
X 
-static inline int B1_rx_full(unsigned short base)
+static inline void t1outp(unsigned int base,
+			  unsigned short offset,
+			  unsigned char value)
+{
+	outb(value, base + offset);
+}
+
+static inline unsigned char t1inp(unsigned int base,
+			          unsigned short offset)
+{
+	return inb(base + offset);
+}
+
+static inline int B1_isfastlink(unsigned int base)
+{
+	return (inb(base + T1_IDENT) & ~0x82) == 1;
+}
+static inline unsigned char B1_fifostatus(unsigned int base)
+{
+	return inb(base + T1_FIFOSTAT);
+}
+
+static inline int B1_rx_full(unsigned int base)
X {
X 	return inb(base + B1_INSTAT) & 0x1;
X }
X 
-static inline unsigned char B1_get_byte(unsigned short base)
+static inline unsigned char B1_get_byte(unsigned int base)
X {
-	unsigned long i = jiffies + 5 * HZ;	/* maximum wait time 5 sec */
+	unsigned long i = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
X 	while (!B1_rx_full(base) && time_before(jiffies, i));
X 	if (B1_rx_full(base))
X 		return inb(base + B1_READ);
-	printk(KERN_CRIT "b1lli: rx not full after 5 second\n");
+	printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base);
X 	return 0;
X }
X 
-static inline unsigned int B1_get_word(unsigned short base)
+static inline unsigned int B1_get_word(unsigned int base)
X {
X 	unsigned int val = 0;
X 	val |= B1_get_byte(base);
@@ -190,18 +290,18 @@
X 	return val;
X }
X 
-static inline int B1_tx_empty(unsigned short base)
+static inline int B1_tx_empty(unsigned int base)
X {
X 	return inb(base + B1_OUTSTAT) & 0x1;
X }
X 
-static inline void B1_put_byte(unsigned short base, unsigned char val)
+static inline void B1_put_byte(unsigned int base, unsigned char val)
X {
X 	while (!B1_tx_empty(base));
X 	b1outp(base, B1_WRITE, val);
X }
X 
-static inline void B1_put_word(unsigned short base, unsigned int val)
+static inline void B1_put_word(unsigned int base, unsigned int val)
X {
X 	B1_put_byte(base, val & 0xff);
X 	B1_put_byte(base, (val >> 8) & 0xff);
@@ -209,26 +309,95 @@
X 	B1_put_byte(base, (val >> 24) & 0xff);
X }
X 
-static inline unsigned int B1_get_slice(unsigned short base,
+static inline unsigned int B1_get_slice(unsigned int base,
X 					unsigned char *dp)
X {
X 	unsigned int len, i;
+#ifdef FASTLINK_DEBUG
+	unsigned wcnt = 0, bcnt = 0;
+#endif
X 
X 	len = i = B1_get_word(base);
-	while (i-- > 0)
-		*dp++ = B1_get_byte(base);
+        if (B1_isfastlink(base)) {
+		int status;
+		while (i > 0) {
+			status = B1_fifostatus(base) & (T1F_IREADY|T1F_IHALF);
+			if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
+
+			switch (status) {
+				case T1F_IREADY|T1F_IHALF|T1F_IFULL:
+					insb(base+B1_READ, dp, FIFO_INPBSIZE);
+					dp += FIFO_INPBSIZE;
+					i -= FIFO_INPBSIZE;
+#ifdef FASTLINK_DEBUG
+					wcnt += FIFO_INPBSIZE;
+#endif
+					break;
+				case T1F_IREADY|T1F_IHALF: 
+					insb(base+B1_READ,dp, i);
+#ifdef FASTLINK_DEBUG
+					wcnt += i;
+#endif
+					dp += i;
+					i = 0;
+					if (i == 0)
+						break;
+					/* fall through */
+				default:
+					*dp++ = B1_get_byte(base);
+					i--;
+#ifdef FASTLINK_DEBUG
+					bcnt++;
+#endif
+					break;
+			}
+	    }
+#ifdef FASTLINK_DEBUG
+	    if (wcnt)
+	    printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n",
+				base, len, wcnt, bcnt);
+#endif
+	} else {
+		while (i-- > 0)
+			*dp++ = B1_get_byte(base);
+	}
X 	return len;
X }
X 
-static inline void B1_put_slice(unsigned short base,
+static inline void B1_put_slice(unsigned int base,
X 				unsigned char *dp, unsigned int len)
X {
-	B1_put_word(base, len);
-	while (len-- > 0)
-		B1_put_byte(base, *dp++);
+	unsigned i = len;
+	B1_put_word(base, i);
+        if (B1_isfastlink(base)) {
+		int status;
+		while (i > 0) {
+			status = B1_fifostatus(base) & (T1F_OREADY|T1F_OHALF);
+			if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY;
+			switch (status) {
+				case T1F_OREADY|T1F_OHALF|T1F_OEMPTY: 
+					outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE);
+					dp += FIFO_OUTBSIZE;
+					i -= FIFO_OUTBSIZE;
+					break;
+				case T1F_OREADY|T1F_OHALF: 
+					outsb(base+B1_WRITE, dp, i);
+					dp += i;
+					i = 0;
+				        break;
+				default:
+					B1_put_byte(base, *dp++);
+					i--;
+					break;
+			}
+		}
+	} else {
+		while (i-- > 0)
+			B1_put_byte(base, *dp++);
+	}
X }
X 
-static void b1_wr_reg(unsigned short base,
+static void b1_wr_reg(unsigned int base,
X                       unsigned int reg,
X 		      unsigned int value)
X {
@@ -237,7 +406,7 @@
X         B1_put_word(base, value);
X }
X 
-static inline unsigned int b1_rd_reg(unsigned short base,
+static inline unsigned int b1_rd_reg(unsigned int base,
X                                      unsigned int reg)
X {
X 	B1_put_byte(base, READ_REGISTER);
@@ -246,14 +415,14 @@
X 	
X }
X 
-static inline void b1_set_test_bit(unsigned short base,
+static inline void b1_set_test_bit(unsigned int base,
X 				   int cardtype,
X 				   int onoff)
X {
X     b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
X }
X 
-static inline int b1_get_test_bit(unsigned short base,
+static inline int b1_get_test_bit(unsigned int base,
X                                   int cardtype)
X {
X     return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
@@ -278,6 +447,26 @@
X  112,				/* irq 15 */
X };
X 
+static int hema_irq_table[16] =
+{0,
+ 0,
+ 0,
+ 0x80,				/* irq 3 */
+ 0,
+ 0x90,				/* irq 5 */
+ 0,
+ 0xA0,				/* irq 7 */
+ 0,
+ 0xB0,				/* irq 9 */
+ 0xC0,				/* irq 10 */
+ 0xD0,				/* irq 11 */
+ 0xE0,				/* irq 12 */
+ 0,
+ 0,
+ 0xF0,				/* irq 15 */
+};
+
+
X int B1_valid_irq(unsigned irq, int cardtype)
X {
X 	switch (cardtype) {
@@ -285,36 +474,76 @@
X 	   case AVM_CARDTYPE_M1:
X 	   case AVM_CARDTYPE_M2:
X 	   case AVM_CARDTYPE_B1:
-	   	return irq_table[irq] != 0;
+	   	return irq_table[irq & 0xf] != 0;
X 	   case AVM_CARDTYPE_T1:
-	   	return irq == 5;
+	   	return hema_irq_table[irq & 0xf] != 0;
+	   case AVM_CARDTYPE_B1PCI:
+		return 1;
X 	}
X }
X 
-unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype)
+int B1_valid_port(unsigned port, int cardtype)
+{
+   switch (cardtype) {
+	   default:
+	   case AVM_CARDTYPE_M1:
+	   case AVM_CARDTYPE_M2:
+	   case AVM_CARDTYPE_B1:
+#if 0	/* problem with PCMCIA and PCI cards */
+		switch (port) {
+			case 0x150:
+			case 0x250:
+			case 0x300:
+			case 0x340:
+				return 1;
+		}
+		return 0;
+#else
+		return 1;
+#endif
+	   case AVM_CARDTYPE_B1PCI:
+		return 1;
+	   case AVM_CARDTYPE_T1:
+		return ((port & 0x7) == 0) && ((port & 0x30) != 0x30);
+   }
+}
+
+void B1_setinterrupt(unsigned int base,
+			         unsigned irq, int cardtype)
X {
X 	switch (cardtype) {
X 	   case AVM_CARDTYPE_T1:
-	      return b1outp(base, B1_IRQ_MASTER, 0x08);
+              t1outp(base, B1_INSTAT, 0x00);
+              t1outp(base, B1_INSTAT, 0x02);
+	      t1outp(base, T1_IRQMASTER, 0x08);
+	      break;
X 	   default:
X 	   case AVM_CARDTYPE_M1:
X 	   case AVM_CARDTYPE_M2:
X 	   case AVM_CARDTYPE_B1:
-	      return b1outp(base, B1_RESET, irq_table[irq]);
+	      b1outp(base, B1_INSTAT, 0x00);
+	      b1outp(base, B1_RESET, irq_table[irq]);
+	      b1outp(base, B1_INSTAT, 0x02);
+	      break;
+	   case AVM_CARDTYPE_B1PCI:
+	      b1outp(base, B1_INSTAT, 0x00);
+	      b1outp(base, B1_RESET, 0xf0);
+	      b1outp(base, B1_INSTAT, 0x02);
+	      break;
X 	 }
X }
X 
-unsigned char B1_enable_irq(unsigned short base)
+unsigned char B1_disable_irq(unsigned int base)
X {
-	return b1outp(base, B1_INSTAT, 0x02);
+	return b1outp(base, B1_INSTAT, 0x00);
X }
X 
-unsigned char B1_disable_irq(unsigned short base)
+void T1_disable_irq(unsigned int base)
X {
-	return b1outp(base, B1_INSTAT, 0x00);
+      t1outp(base, T1_IRQMASTER, 0x00);
X }
X 
-void B1_reset(unsigned short base)
+void B1_reset(unsigned int base)
X {
X 	b1outp(base, B1_RESET, 0);
X 	udelay(55 * 2 * 1000);	/* 2 TIC's */
@@ -326,7 +555,19 @@
X 	udelay(55 * 2 * 1000);	/* 2 TIC's */
X }
X 
-int B1_detect(unsigned short base, int cardtype)
+void T1_reset(unsigned int base)
+{
+        /* reset T1 Controller */
+        B1_reset(base);
+        /* disable irq on HEMA */
+        t1outp(base, B1_INSTAT, 0x00);
+        t1outp(base, B1_OUTSTAT, 0x00);
+        t1outp(base, T1_IRQMASTER, 0x00);
+        /* reset HEMA board configuration */
+	t1outp(base, T1_RESETBOARD, 0xf);
+}
+
+int B1_detect(unsigned int base, int cardtype)
X {
X 	int onoff, i;
X 
@@ -372,10 +613,79 @@
X 	return 0;
X }
X 
+int T1_detectandinit(unsigned int base, unsigned irq, int cardnr)
+{
+	unsigned char cregs[8];
+	unsigned char reverse_cardnr;
+	unsigned long flags;
+	unsigned char dummy;
+	int i;
+
+	reverse_cardnr =   ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
+		         | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
+	cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
+	cregs[1] = 0x00; /* fast & slow link connected to CON1 */
+	cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
+	cregs[3] = 0;
+	cregs[4] = 0x11; /* zero wait state */
+	cregs[5] = hema_irq_table[irq & 0xf];
+	cregs[6] = 0;
+	cregs[7] = 0;
+
+	save_flags(flags);
+	cli();
+	/* board reset */
+	t1outp(base, T1_RESETBOARD, 0xf);
+	udelay(100 * 1000);
+	dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
+
+	/* write config */
+	dummy = (base >> 4) & 0xff;
+	for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
+	t1outp(base, HEMA_PAL_ID & 0xf, dummy);
+	t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
+	for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
+	t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
+	restore_flags(flags);
+
+	udelay(100 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+	udelay(10 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
+	udelay(100 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+	udelay(10 * 1000);
+	t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
+	udelay(5 * 1000);
+	t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
+
+	if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+		return 1;
+	if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
+		return 2;
+	if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
+		return 3;
+	if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
+		return 4;
+	if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
+		return 5;
+	if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
+		return 6;
+	if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+		return 7;
+	if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
+		return 8;
+	if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
+		return 9;
+        return 0;
+}
X 
X extern int loaddebug;
X 
-int B1_load_t4file(unsigned short base, avmb1_t4file * t4file)
+int B1_load_t4file(unsigned int base, avmb1_t4file * t4file)
X {
X 	/*
X 	 * Data is in user space !!!
@@ -414,7 +724,7 @@
X 	return 0;
X }
X 
-int B1_load_config(unsigned short base, avmb1_t4file * config)
+int B1_load_config(unsigned int base, avmb1_t4file * config)
X {
X 	/*
X 	 * Data is in user space !!!
@@ -470,7 +780,7 @@
X 	return 0;
X }
X 
-int B1_loaded(unsigned short base)
+int B1_loaded(unsigned int base)
X {
X 	int i;
X 	unsigned char ans;
@@ -482,7 +792,7 @@
X 			break;
X 	}
X 	if (!B1_tx_empty(base)) {
-		printk(KERN_ERR "b1lli: B1_loaded: timeout tx\n");
+		printk(KERN_ERR "b1lli(0x%x): B1_loaded: timeout tx\n", base);
X 		return 0;
X 	}
X 	B1_put_byte(base, SEND_POLL);
@@ -494,11 +804,12 @@
X 					printk(KERN_DEBUG "b1capi: loaded: ok\n");
X 				return 1;
X 			}
-			printk(KERN_ERR "b1lli: B1_loaded: got 0x%x ???\n", ans);
+			printk(KERN_ERR "b1lli(0x%x): B1_loaded: got 0x%x ???\n",
+				base, ans);
X 			return 0;
X 		}
X 	}
-	printk(KERN_ERR "b1lli: B1_loaded: timeout rx\n");
+	printk(KERN_ERR "b1lli(0x%x): B1_loaded: timeout rx\n", base);
X 	return 0;
X }
X 
@@ -519,7 +830,7 @@
X  * ------------------------------------------------------------------- 
X  */
X 
-void B1_send_init(unsigned short port,
+void B1_send_init(unsigned int port,
X 	     unsigned int napps, unsigned int nncci, unsigned int cardnr)
X {
X 	unsigned long flags;
@@ -533,7 +844,7 @@
X 	restore_flags(flags);
X }
X 
-void B1_send_register(unsigned short port,
+void B1_send_register(unsigned int port,
X 		      __u16 appid, __u32 nmsg,
X 		      __u32 nb3conn, __u32 nb3blocks, __u32 b3bsize)
X {
@@ -550,7 +861,7 @@
X 	restore_flags(flags);
X }
X 
-void B1_send_release(unsigned short port,
+void B1_send_release(unsigned int port,
X 		     __u16 appid)
X {
X 	unsigned long flags;
@@ -562,9 +873,7 @@
X 	restore_flags(flags);
X }
X 
-extern int showcapimsgs;
-
-void B1_send_message(unsigned short port, struct sk_buff *skb)
+void B1_send_message(unsigned int port, struct sk_buff *skb)
X {
X 	unsigned long flags;
X 	__u16 len = CAPIMSG_LEN(skb->data);
@@ -630,6 +939,7 @@
X 	unsigned NCCI;
X 	unsigned WindowSize;
X 
+t1retry:
X 	if (!B1_rx_full(card->port))
X 		return;
X 
@@ -704,7 +1014,7 @@
X 		WindowSize = B1_get_word(card->port);
X 
X 		if (showcapimsgs)
-			printk(KERN_DEBUG "b1lli: NEW_NCCI app %u ncci 0x%x\n", ApplId, NCCI);
+			printk(KERN_DEBUG "b1lli(0x%x): NEW_NCCI app %u ncci 0x%x\n", card->port, ApplId, NCCI);
X 
X 		avmb1_handle_new_ncci(card, ApplId, NCCI, WindowSize);
X 
@@ -716,19 +1026,23 @@
X 		NCCI = B1_get_word(card->port);
X 
X 		if (showcapimsgs)
-			printk(KERN_DEBUG "b1lli: FREE_NCCI app %u ncci 0x%x\n", ApplId, NCCI);
+			printk(KERN_DEBUG "b1lli(0x%x): FREE_NCCI app %u ncci 0x%x\n", card->port, ApplId, NCCI);
X 
X 		avmb1_handle_free_ncci(card, ApplId, NCCI);
X 		break;
X 
X 	case RECEIVE_START:
+                if (card->cardtype == AVM_CARDTYPE_T1) {
+	           B1_put_byte(card->port, SEND_POLLACK);
+		   /* printk(KERN_DEBUG "b1lli: T1 watchdog\n"); */
+                }
X 		if (card->blocked)
-			printk(KERN_DEBUG "b1lli: RESTART\n");
+			printk(KERN_DEBUG "b1lli(0x%x): RESTART\n", card->port);
X 		card->blocked = 0;
X 		break;
X 
X 	case RECEIVE_STOP:
-		printk(KERN_DEBUG "b1lli: STOP\n");
+		printk(KERN_DEBUG "b1lli(0x%x): STOP\n", card->port);
X 		card->blocked = 1;
X 		break;
X 
@@ -737,13 +1051,24 @@
X 		card->versionlen = B1_get_slice(card->port, card->versionbuf);
X 		card->cardstate = CARD_ACTIVE;
X 		parse_version(card);
-		printk(KERN_INFO "b1lli: %s-card (%s) now active\n",
+		printk(KERN_INFO "b1lli(0x%x): %s-card (%s) now active\n",
+		       card->port,
X 		       card->version[VER_CARDTYPE],
X 		       card->version[VER_DRIVER]);
X 		avmb1_card_ready(card);
X 		break;
+        case RECEIVE_TASK_READY:
+		ApplId = (unsigned) B1_get_word(card->port);
+		MsgLen = B1_get_slice(card->port, card->msgbuf);
+		card->msgbuf[MsgLen] = 0;
+		printk(KERN_INFO "b1lli(0x%x): Task %d \"%s\" ready.\n",
+				card->port, ApplId, card->msgbuf);
+		break;
X 	default:
-		printk(KERN_ERR "b1lli: B1_handle_interrupt: 0x%x ???\n", b1cmd);
+		printk(KERN_ERR "b1lli(0x%x): B1_handle_interrupt: 0x%x ???\n",
+				card->port, b1cmd);
X 		break;
X 	}
+	if (card->cardtype == AVM_CARDTYPE_T1) 
+		goto t1retry;
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- v2.3.3/linux/drivers/isdn/avmb1/b1pci.c	Thu May 21 13:45:01 1998
+++ linux/drivers/isdn/avmb1/b1pci.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,29 @@
X /*
- * $Id: b1pci.c,v 1.5 1998/01/31 11:14:43 calle Exp $
+ * $Id: b1pci.c,v 1.9 1999/04/15 19:49:32 calle Exp $
X  * 
X  * Module for AVM B1 PCI-card.
X  * 
X  * (c) Copyright 1997 by Carsten Paeth (ca...@calle.in-berlin.de)
X  * 
X  * $Log: b1pci.c,v $
+ * Revision 1.9  1999/04/15 19:49:32  calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.8  1998/06/17 19:51:16  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.7  1998/03/29 16:06:02  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.2.2.2  1998/01/23 16:49:30  calle
+ * added functions for pcmcia cards,
+ * avmb1_addcard returns now the controller number.
+ *
+ * Revision 1.6  1998/02/25 09:15:36  fritz
+ * apply Martin's pci driver patch to isdn drivers (vgerCVS)
+ *
X  * Revision 1.5  1998/01/31 11:14:43  calle
X  * merged changes to 2.0 tree, prepare 2.1.82 to work.
X  *
@@ -44,7 +62,7 @@
X #define PCI_DEVICE_ID_AVM_B1	0x700
X #endif
X 
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.9 $";
X 
X /* ------------------------------------------------------------- */
X 
@@ -93,13 +111,13 @@
X 		printk(KERN_INFO
X 			"b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
X 			ioaddr, irq);
-		if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1)) != 0) {
+		if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1PCI)) != 0) {
X 		        printk(KERN_ERR
X 			"b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
X 			ioaddr, irq);
X 			return rc;
X 		}
-		if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1)) < 0)
+		if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1PCI)) < 0)
X 			return rc;
X 	}
X 	return 0;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.3.3/linux/drivers/isdn/avmb1/capi.c	Mon Aug 24 13:02:44 1998
+++ linux/drivers/isdn/avmb1/capi.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,23 @@
X /*
- * $Id: capi.c,v 1.10 1998/02/13 07:09:13 calle Exp $
+ * $Id: capi.c,v 1.13 1998/08/28 04:32:25 calle Exp $
X  *
X  * CAPI 2.0 Interface for Linux
X  *
X  * Copyright 1996 by Carsten Paeth (ca...@calle.in-berlin.de)
X  *
X  * $Log: capi.c,v $
+ * Revision 1.13  1998/08/28 04:32:25  calle
+ * Added patch send by Michael....@post.rwth-aachen.de, to get AVM B1
+ * driver running with 2.1.118.
+ *
+ * Revision 1.12  1998/05/26 22:39:34  he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.11  1998/03/09 17:46:37  he
+ * merged in 2.1.89 changes
+ *
X  * Revision 1.10  1998/02/13 07:09:13  calle
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -237,6 +249,9 @@
X 		return POLLERR;
X 
X 	cdev = &capidevs[minor];
+#if (LINUX_VERSION_CODE < 0x020159) /* 2.1.89 */
+#define poll_wait(f,wq,w) poll_wait((wq),(w))
+#endif
X 	poll_wait(file, &(cdev->recv_wait), wait);
X 	mask = POLLOUT | POLLWRNORM;
X 	if (!skb_queue_empty(&cdev->recv_queue))
@@ -464,7 +479,9 @@
X 	capi_ioctl,
X 	NULL,			/* capi_mmap */
X 	capi_open,
-	NULL,			/* flush */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118)
+        NULL,                   /* capi_flush */
+#endif
X 	capi_release,
X 	NULL,			/* capi_fsync */
X 	NULL,			/* capi_fasync */
@@ -484,7 +501,16 @@
X 
X int capi_init(void)
X {
+#if LINUX_VERSION_CODE >= 131841
+	int j;
+#endif
+	
X 	memset(capidevs, 0, sizeof(capidevs));
+#if LINUX_VERSION_CODE >= 131841
+	for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) {
+		init_waitqueue_head(&capidevs[j].recv_wait);
+	}
+#endif
X 
X 	if (register_chrdev(capi_major, "capi20", &capi_fops)) {
X 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
@@ -496,6 +522,7 @@
X 		unregister_chrdev(capi_major, "capi20");
X 		return -EIO;
X 	}
+	
X 	return 0;
X }
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/capidev.h linux/drivers/isdn/avmb1/capidev.h
--- v2.3.3/linux/drivers/isdn/avmb1/capidev.h	Mon May 17 09:55:22 1999
+++ linux/drivers/isdn/avmb1/capidev.h	Sun May 23 10:03:41 1999
@@ -22,7 +22,11 @@
X 	int is_registered;
X 	__u16 applid;
X 	struct sk_buff_head recv_queue;
+#if LINUX_VERSION_CODE < 131841
+	struct wait_queue *recv_wait;
+#else
X 	wait_queue_head_t recv_wait;
+#endif
X 	__u16 errcode;
X };
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c
--- v2.3.3/linux/drivers/isdn/avmb1/capidrv.c	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/avmb1/capidrv.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,36 @@
X /*
- * $Id: capidrv.c,v 1.11 1998/02/13 07:09:15 calle Exp $
+ * $Id: capidrv.c,v 1.13 1998/06/26 15:12:55 fritz Exp $
X  *
X  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
X  *
X  * Copyright 1997 by Carsten Paeth (ca...@calle.in-berlin.de)
X  *
X  * $Log: capidrv.c,v $
+ * Revision 1.13  1998/06/26 15:12:55  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.12  1998/03/29 16:06:03  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.3.2.10  1998/03/20 14:38:24  calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.3.2.9  1998/03/20 09:01:12  calle
+ * Changes capi_register handling to get full support for 30 bchannels.
+ *
+ * Revision 1.3.2.8  1998/03/18 17:51:28  calle
+ * added controller number to error messages
+ *
+ * Revision 1.3.2.7  1998/02/27 15:40:47  calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
X  * Revision 1.11  1998/02/13 07:09:15  calle
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -79,7 +104,7 @@
X #include "capicmd.h"
X #include "capidrv.h"
X 
-static char *revision = "$Revision: 1.11 $";
+static char *revision = "$Revision: 1.13 $";
X int debugmode = 0;
X 
X MODULE_AUTHOR("Carsten Paeth <ca...@calle.in-berlin.de>");
@@ -378,8 +403,8 @@
X 			return;
X 		}
X 	}
-	printk(KERN_ERR "capidrv: free_plci %p (0x%x) not found, Huh?\n",
-	       plcip, plcip->plci);
+	printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
+	       card->contrnr, plcip, plcip->plci);
X }
X 
X /* -------- ncci management ------------------------------------------ */
@@ -512,15 +537,15 @@
X 
X static struct listenstatechange listentable[] =
X {
-	{ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
-	{ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
-	{ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
-    {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
-	{ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
-      {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
-	{ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
-	{ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
-	{},
+  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
+  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
+  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
+  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
+  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
+  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
+  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
+  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
+  {},
X };
X 
X static void listen_change_state(capidrv_contr * card, int event)
@@ -529,15 +554,15 @@
X 	while (p->event) {
X 		if (card->state == p->actstate && p->event == event) {
X 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: listen_change_state %d -> %d\n",
-				       card->state, p->nextstate);
+				printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
+				       card->contrnr, card->state, p->nextstate);
X 			card->state = p->nextstate;
X 			return;
X 		}
X 		p++;
X 	}
-	printk(KERN_ERR "capidrv: listen_change_state state=%d event=%d ????\n",
-	       card->state, event);
+	printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
+	       card->contrnr, card->state, event);
X 
X }
X 
@@ -567,46 +592,57 @@
X static struct plcistatechange plcitable[] =
X {
X   /* P-0 */
-	{ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
-	{ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
-	{ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
+  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
+  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
+  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
+  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},
X   /* P-0.1 */
-	{ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
-	{ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
-    {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
+  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
+  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
X   /* P-1 */
-      {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-   {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-{ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-    {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
X   /* P-ACT */
-      {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-   {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-	{ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},
X   /* P-2 */
-    {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
-    {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
-	{ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
-    {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-     {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},
X   /* P-3 */
-{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
-{ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-	{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
X   /* P-4 */
-      {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-   {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-{ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-    {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
X   /* P-5 */
-{ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
X   /* P-6 */
-	{ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
-	{},
+  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
+  /* P-0.Res */
+  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
+  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},
+  /* P-RES */
+  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},
+  /* P-HELD */
+  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},
+  {},
X };
X 
X static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
@@ -615,8 +651,8 @@
X 	while (p->event) {
X 		if (plci->state == p->actstate && p->event == event) {
X 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: plci_change_state:0x%x %d -> %d\n",
-				  plci->plci, plci->state, p->nextstate);
+				printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
+				  card->contrnr, plci->plci, plci->state, p->nextstate);
X 			plci->state = p->nextstate;
X 			if (p->changefunc)
X 				p->changefunc(card, plci);
@@ -624,8 +660,8 @@
X 		}
X 		p++;
X 	}
-	printk(KERN_ERR "capidrv: plci_change_state:0x%x state=%d event=%d ????\n",
-	       plci->plci, plci->state, event);
+	printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
+	       card->contrnr, plci->plci, plci->state, event);
X }
X 
X /* ------------------------------------------------------------------ */
@@ -642,7 +678,7 @@
X 				 ncci->plcip->plci,
X 				 0,	/* BChannelinformation */
X 				 0,	/* Keypadfacility */
-				 0,	/* Useruserdata */
+				 0,	/* Useruserdata */   /* $$$$ */
X 				 0	/* Facilitydataarray */
X 	);
X 	send_message(card, &cmsg);
@@ -667,34 +703,35 @@
X static struct nccistatechange nccitable[] =
X {
X   /* N-0 */
-	{ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
-	{ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
+  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
+  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
X   /* N-0.1 */
-    {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
-      {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, 0},
+  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
+  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
X   /* N-1 */
- {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
-	{ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
+  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
+  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
X   {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
X   /* N-2 */
-   {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
- {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-{ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
+  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
X   /* N-ACT */
-	{ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
-    {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-   {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
X   /* N-3 */
-	{ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
+  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
X   {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
X   /* N-4 */
-	{ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-	{ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR, 0},
+  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},
X   /* N-5 */
-    {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
-	{},
+  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
+  {},
X };
X 
X static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
@@ -703,8 +740,8 @@
X 	while (p->event) {
X 		if (ncci->state == p->actstate && p->event == event) {
X 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: ncci_change_state:0x%x %d -> %d\n",
-				  ncci->ncci, ncci->state, p->nextstate);
+				printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
+				  card->contrnr, ncci->ncci, ncci->state, p->nextstate);
X 			if (p->nextstate == ST_NCCI_PREVIOUS) {
X 				ncci->state = ncci->oldstate;
X 				ncci->oldstate = p->actstate;
@@ -718,8 +755,8 @@
X 		}
X 		p++;
X 	}
-	printk(KERN_ERR "capidrv: ncci_change_state:0x%x state=%d event=%d ????\n",
-	       ncci->ncci, ncci->state, event);
+	printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
+	       card->contrnr, ncci->ncci, ncci->state, event);
X }
X 
X /* ------------------------------------------------------------------- */
@@ -752,8 +789,8 @@
X 
X 	case CAPI_LISTEN_CONF:	/* Controller */
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
-			       cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
+			printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
+			       card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
X 		if (cmsg->Info) {
X 			listen_change_state(card, EV_LISTEN_CONF_ERROR);
X 		} else if (card->cipmask == 0) {
@@ -789,7 +826,8 @@
X 		      handle_dtrace_data(card, direction, 0, data, len);
X 		      break;
X 		   }
-	           printk(KERN_INFO "capidrv: %s from controller 0x%x layer 0x%x, ignored\n",
+	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
+                        card->contrnr, 
X 			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			cmsg->adr.adrController, layer);
X                    break;
@@ -805,7 +843,8 @@
X 		      default: s = "unkown error"; break;
X 		   }
X 		   if (s)
-	           printk(KERN_INFO "capidrv: %s from controller 0x%x function %d: %s\n",
+	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
+			card->contrnr,
X 			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			cmsg->adr.adrController,
X 			cmsg->Function, s);
@@ -822,14 +861,16 @@
X 		goto ignored;
X 
X 	default:
-		printk(KERN_ERR "capidrv: got %s from controller 0x%x ???",
+		printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
+		       card->contrnr,
X 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 		       cmsg->adr.adrController);
X 	}
X 	return;
X 
X       ignored:
-	printk(KERN_INFO "capidrv: %s from controller 0x%x ignored\n",
+	printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
+	       card->contrnr,
X 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 	       cmsg->adr.adrController);
X }
@@ -842,12 +883,12 @@
X 	int chan;
X 
X 	if ((chan = new_bchan(card)) == -1) {
-		printk(KERN_ERR "capidrv: incoming call on not existing bchan ?\n");
+		printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
X 		return;
X 	}
X 	bchan = &card->bchans[chan];
X 	if ((plcip = new_plci(card, chan)) == 0) {
-		printk(KERN_ERR "capidrv: incoming call: no memory, sorry.\n");
+		printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
X 		return;
X 	}
X 	bchan->incoming = 1;
@@ -869,7 +910,8 @@
X 	cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
X 	cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
X 
-	printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s\n", 
+	printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", 
+			card->contrnr,
X 			cmd.parm.setup.phone,
X 			cmd.parm.setup.si1,
X 			cmd.parm.setup.si2,
@@ -877,6 +919,7 @@
X 
X 	switch (card->interface.statcallb(&cmd)) {
X 	case 0:
+	case 3:
X 		/* No device matching this call.
X 		 * and isdn_common.c has send a HANGUP command
X 		 * which is ignored in state ST_PLCI_INCOMING,
@@ -886,7 +929,8 @@
X 		cmsg->Reject = 1;	/* ignore */
X 		send_message(card, cmsg);
X 		plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
-		printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s ignored\n",
+		printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
+			card->contrnr,
X 			cmd.parm.setup.phone,
X 			cmd.parm.setup.si1,
X 			cmd.parm.setup.si2,
@@ -903,7 +947,8 @@
X 		 * and CONNECT_RESP already sent.
X 		 */
X 		if (plcip->state == ST_PLCI_INCOMING) {
-			printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s tty alerting\n",
+			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
+				card->contrnr,
X 				cmd.parm.setup.phone,
X 				cmd.parm.setup.si1,
X 				cmd.parm.setup.si2,
@@ -920,7 +965,8 @@
X 			plcip->msgid = cmsg->Messagenumber;
X 			send_message(card, cmsg);
X 		} else {
-			printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s on netdev\n",
+			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
+				card->contrnr,
X 				cmd.parm.setup.phone,
X 				cmd.parm.setup.si1,
X 				cmd.parm.setup.si2,
@@ -963,7 +1009,8 @@
X 
X 	case CAPI_DISCONNECT_IND:	/* plci */
X 		if (cmsg->Reason) {
-			printk(KERN_INFO "capidrv: %s reason 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
X 		}
@@ -981,7 +1028,8 @@
X 
X 	case CAPI_DISCONNECT_CONF:	/* plci */
X 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->Info, capi_info2str(cmsg->Info), 
X 			       cmsg->adr.adrPLCI);
@@ -994,7 +1042,8 @@
X 
X 	case CAPI_ALERT_CONF:	/* plci */
X 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->Info, capi_info2str(cmsg->Info), 
X 			       cmsg->adr.adrPLCI);
@@ -1007,7 +1056,8 @@
X 
X 	case CAPI_CONNECT_CONF:	/* plci */
X 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->Info, capi_info2str(cmsg->Info), 
X 			       cmsg->adr.adrPLCI);
@@ -1040,7 +1090,7 @@
X 			nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
X 
X 			if (!nccip) {
-				printk(KERN_ERR "capidrv: no mem for ncci, sorry\n");
+				printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
X 				break;	/* $$$$ */
X 			}
X 			capi_fill_CONNECT_B3_REQ(cmsg,
@@ -1080,7 +1130,8 @@
X 				break;
X 			}
X 		}
-		printk(KERN_ERR "capidrv: %s\n", capi_cmsg2str(cmsg));
+		printk(KERN_ERR "capidrv-%d: %s\n",
+				card->contrnr, capi_cmsg2str(cmsg));
X 		break;
X 
X 	case CAPI_CONNECT_ACTIVE_CONF:		/* plci */
@@ -1096,18 +1147,21 @@
X 		goto ignored;
X 
X 	default:
-		printk(KERN_ERR "capidrv: got %s for plci 0x%x ???",
+		printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
+		       card->contrnr,
X 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 		       cmsg->adr.adrPLCI);
X 	}
X 	return;
X       ignored:
-	printk(KERN_INFO "capidrv: %s for plci 0x%x ignored\n",
+	printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
+	       card->contrnr,
X 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 	       cmsg->adr.adrPLCI);
X 	return;
X       notfound:
-	printk(KERN_ERR "capidrv: %s: plci 0x%x not found\n",
+	printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
+	       card->contrnr,
X 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 	       cmsg->adr.adrPLCI);
X 	return;
@@ -1142,8 +1196,8 @@
X 		cmd.arg = nccip->chan;
X 		card->interface.statcallb(&cmd);
X 
-		printk(KERN_INFO "capidrv: chan %d up with ncci 0x%x\n",
-		       nccip->chan, nccip->ncci);
+		printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
+		       card->contrnr, nccip->chan, nccip->ncci);
X 		break;
X 
X 	case CAPI_CONNECT_B3_ACTIVE_CONF:	/* ncci */
@@ -1167,9 +1221,10 @@
X 				ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
X 				break;
X 			}
-			printk(KERN_ERR "capidrv: no mem for ncci, sorry\n");
+			printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",							card->contrnr);
X 		} else {
-			printk(KERN_ERR "capidrv: %s: plci for ncci 0x%x not found\n",
+			printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->adr.adrNCCI);
X 		}
@@ -1192,7 +1247,8 @@
X 
X 		nccip->ncci = cmsg->adr.adrNCCI;
X 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->Info, capi_info2str(cmsg->Info), 
X 			       cmsg->adr.adrNCCI);
@@ -1242,7 +1298,8 @@
X 		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
X 			goto notfound;
X 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
+			   card->contrnr,
X 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 			       cmsg->Info, capi_info2str(cmsg->Info), 
X 			       cmsg->adr.adrNCCI);
@@ -1251,6 +1308,9 @@
X 		break;
X 
X 	case CAPI_RESET_B3_IND:	/* ncci */
+		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
+			goto notfound;
+		ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
X 		capi_cmsg_answer(cmsg);
X 		send_message(card, cmsg);
X 		break;
@@ -1264,18 +1324,21 @@
X 		goto ignored;
X 
X 	default:
-		printk(KERN_ERR "capidrv: got %s for ncci 0x%x ???",
+		printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
+		       card->contrnr,
X 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 		       cmsg->adr.adrNCCI);
X 	}
X 	return;
X       ignored:
-	printk(KERN_INFO "capidrv: %s for ncci 0x%x ignored\n",
+	printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
+	       card->contrnr,
X 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 	       cmsg->adr.adrNCCI);
X 	return;
X       notfound:
-	printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n",
+	printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
+	       card->contrnr,
X 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 	       cmsg->adr.adrNCCI);
X }
@@ -1293,7 +1356,8 @@
X 		return;
X 	}
X 	if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
-		printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n",
+		printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
+		       card->contrnr,
X 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
X 		       cmsg->adr.adrNCCI);
X 		kfree_skb(skb);
@@ -1314,7 +1378,8 @@
X 	while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) {
X 		capi_message2cmsg(&s_cmsg, skb->data);
X 		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv_signal: %s\n", capi_cmsg2str(&s_cmsg));
+			printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
+					applid, capi_cmsg2str(&s_cmsg));
X 
X 		if (s_cmsg.Command == CAPI_DATA_B3
X 		    && s_cmsg.Subcommand == CAPI_IND) {
@@ -1348,7 +1413,8 @@
X     isdn_ctrl cmd;
X 
X     if (!len) {
-       printk(KERN_DEBUG "avmb1_q931_data: len == %d\n", len);
+       printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 12'
echo 'File patch-2.3.4 is continued in part 13'
echo 13 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 13 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+				card->contrnr, len);
X        return;
X     }
X 
@@ -1393,7 +1459,8 @@
X {
X 	switch (c->arg) {
X 	default:
-		printk(KERN_DEBUG "capidrv: capidrv_ioctl(%ld) called ??\n", c->arg);
+		printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
+				card->contrnr, c->arg);
X 		return -EINVAL;
X 	}
X 	return -EINVAL;
@@ -1414,7 +1481,8 @@
X 			__u8 called[ISDN_MSNLEN + 2];
X 
X 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
+				printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
+					card->contrnr,
X 					c->arg,
X 				        c->parm.setup.phone,
X 				        c->parm.setup.si1,
@@ -1424,7 +1492,8 @@
X 			bchan = &card->bchans[c->arg % card->nbchan];
X 
X 			if (bchan->plcip) {
-				printk(KERN_ERR "capidrv: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
+				printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
+					card->contrnr,
X 			        	c->arg, 
X 				        c->parm.setup.phone,
X 				        c->parm.setup.si1,
@@ -1486,10 +1555,11 @@
X 
X 	case ISDN_CMD_ACCEPTD:
X 
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTD(ch=%ld)\n",
-			       c->arg);
X 		bchan = &card->bchans[c->arg % card->nbchan];
+		if (debugmode)
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
+			       card->contrnr,
+			       c->arg, bchan->l2, bchan->l3);
X 
X 		capi_fill_CONNECT_RESP(&cmdcmsg,
X 				       global.appid,
@@ -1517,19 +1587,22 @@
X 
X 	case ISDN_CMD_ACCEPTB:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTB(ch=%ld)\n",
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
+			       card->contrnr,
X 			       c->arg);
X 		return -ENOSYS;
X 
X 	case ISDN_CMD_HANGUP:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_HANGUP(ch=%ld)\n",
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
+			       card->contrnr,
X 			       c->arg);
X 		bchan = &card->bchans[c->arg % card->nbchan];
X 
X 		if (bchan->disconnecting) {
X 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: chan %ld already disconnecting ...\n",
+				printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
+				       card->contrnr,
X 				       c->arg);
X 			return 0;
X 		}
@@ -1568,23 +1641,26 @@
X 
X 	case ISDN_CMD_SETL2:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: set L2 on chan %ld to %ld\n",
+			printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
+			       card->contrnr,
X 			       (c->arg & 0xff), (c->arg >> 8));
-		bchan = &card->bchans[c->arg % card->nbchan];
+		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
X 		bchan->l2 = (c->arg >> 8);
X 		return 0;
X 
X 	case ISDN_CMD_SETL3:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: set L3 on chan %ld to %ld\n",
+			printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
+			       card->contrnr,
X 			       (c->arg & 0xff), (c->arg >> 8));
-		bchan = &card->bchans[c->arg % card->nbchan];
+		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
X 		bchan->l3 = (c->arg >> 8);
X 		return 0;
X 
X 	case ISDN_CMD_SETEAZ:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: set EAZ \"%s\" on chan %ld\n",
+			printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
+			       card->contrnr,
X 			       c->parm.num, c->arg);
X 		bchan = &card->bchans[c->arg % card->nbchan];
X 		strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
@@ -1592,46 +1668,54 @@
X 
X 	case ISDN_CMD_CLREAZ:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: clearing EAZ on chan %ld\n", c->arg);
+			printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
+					card->contrnr, c->arg);
X 		bchan = &card->bchans[c->arg % card->nbchan];
X 		bchan->msn[0] = 0;
X 		return 0;
X 
X 	case ISDN_CMD_LOCK:
X 		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_LOCK (%ld)\n", c->arg);
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);
X 		MOD_INC_USE_COUNT;
X 		break;
X 
X 	case ISDN_CMD_UNLOCK:
X 		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_UNLOCK (%ld)\n", c->arg);
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
+					card->contrnr, c->arg);
X 		MOD_DEC_USE_COUNT;
X 		break;
X 
X /* never called */
X 	case ISDN_CMD_GETL2:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL2\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",
+					card->contrnr);
X 		return -ENODEV;
X 	case ISDN_CMD_GETL3:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL3\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",
+					card->contrnr);
X 		return -ENODEV;
X 	case ISDN_CMD_GETEAZ:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETEAZ\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",
+					card->contrnr);
X 		return -ENODEV;
X 	case ISDN_CMD_SETSIL:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_SETSIL\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",
+					card->contrnr);
X 		return -ENODEV;
X 	case ISDN_CMD_GETSIL:
X 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETSIL\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",
+					card->contrnr);
X 		return -ENODEV;
X 	default:
-		printk(KERN_ERR "capidrv: ISDN_CMD_%d, Huh?\n", c->command);
+		printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
+					card->contrnr, c->command);
X 		return -EINVAL;
X 	}
X 	return 0;
@@ -1645,8 +1729,8 @@
X 		return capidrv_command(c, card);
X 
X 	printk(KERN_ERR
-	     "capidrv: if_command %d called with invalid driverId %d!\n",
-	       c->command, c->driver);
+	     "capidrv-%d: if_command %d called with invalid driverId %d!\n",
+	       card->contrnr, c->command, c->driver);
X 	return -ENODEV;
X }
X 
@@ -1663,15 +1747,15 @@
X 	__u16 datahandle;
X 
X 	if (!card) {
-		printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
-		       id);
+		printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
+		       card->contrnr, id);
X 		return 0;
X 	}
X 	bchan = &card->bchans[channel % card->nbchan];
X 	nccip = bchan->nccip;
X 	if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
-		printk(KERN_ERR "capidrv: if_sendbuf: %s:%d: chan not up!\n",
-		       card->name, channel);
+		printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
+		       card->contrnr, card->name, channel);
X 		return 0;
X 	}
X 	datahandle = nccip->datahandle;
@@ -1691,13 +1775,14 @@
X 	if (skb_headroom(skb) < msglen) {
X 		struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len);
X 		if (!nskb) {
-			printk(KERN_ERR "capidrv: if_sendbuf: no memory\n");
+			printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
+				card->contrnr);
X 		        (void)capidrv_del_ack(nccip, datahandle);
X 			return 0;
X 		}
X #if 0
-		printk(KERN_DEBUG "capidrv: only %d bytes headroom\n",
-		       skb_headroom(skb));
+		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom\n",
+		       card->contrnr, skb_headroom(skb));
X #endif
X 		memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen);
X 		memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
@@ -1729,8 +1814,8 @@
X 	__u8 *p;
X 
X 	if (!card) {
-		printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
-		       id);
+		printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",
+		       card->contrnr, id);
X 		return -ENODEV;
X 	}
X 
@@ -1776,7 +1861,7 @@
X 	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
X 	avmversion[2] |= version.minormanuversion & 0x0f;
X 
-        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
+        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) {
X 		printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
X 		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
X 					   card->msgid++,
@@ -1878,7 +1963,8 @@
X 	printk(KERN_INFO "%s: now up (%d B channels)\n",
X 		card->name, card->nbchan);
X 
-        enable_dchannel_trace(card);
+        if (card->nbchan == 2)  /* no T1 */
+        	enable_dchannel_trace(card);
X 
X 	return 0;
X }
@@ -1965,8 +2051,8 @@
X 	} else
X 		strcpy(rev, " ??? ");
X 
-	rparam.level3cnt = 2;
-	rparam.datablkcnt = 8;
+	rparam.level3cnt = -2;  /* number of bchannels twice */
+	rparam.datablkcnt = 16;
X 	rparam.datablklen = 2048;
X 	errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
X 	if (errcode) {
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/capidrv.h linux/drivers/isdn/avmb1/capidrv.h
--- v2.3.3/linux/drivers/isdn/avmb1/capidrv.h	Thu May 29 21:53:05 1997
+++ linux/drivers/isdn/avmb1/capidrv.h	Sun May 23 10:03:41 1999
@@ -1,11 +1,22 @@
X /*
- * $Id: capidrv.h,v 1.1 1997/03/04 21:50:33 calle Exp $
+ * $Id: capidrv.h,v 1.2 1998/03/29 16:06:06 calle Exp $
X  *
X  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
X  *
X  * Copyright 1997 by Carsten Paeth (ca...@calle.in-berlin.de)
X  *
X  * $Log: capidrv.h,v $
+ * Revision 1.2  1998/03/29 16:06:06  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.1 1998/03/20 14:38:28 calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
X  * Revision 1.1  1997/03/04 21:50:33  calle
X  * Frirst version in isdn4linux
X  *
@@ -49,34 +60,70 @@
X #define ST_PLCI_ACCEPTING		6	/* P-4 */
X #define ST_PLCI_DISCONNECTING		7	/* P-5 */
X #define ST_PLCI_DISCONNECTED		8	/* P-6 */
+#define ST_PLCI_RESUMEING		9	/* P-0.Res */
+#define ST_PLCI_RESUME			10	/* P-Res */
+#define ST_PLCI_HELD			11	/* P-HELD */
X 
-#define EV_PLCI_CONNECT_REQ		1	/* P-0 -> P-0.1 */
-#define EV_PLCI_CONNECT_CONF_ERROR	2	/* P-0.1 -> P-0 */
-#define EV_PLCI_CONNECT_CONF_OK		3	/* P-0.1 -> P-1 */
-#define EV_PLCI_FACILITY_IND_UP		4	/* P-0 -> P-1 */
-#define EV_PLCI_CONNECT_IND		5	/* P-0 -> P-2 */
-#define EV_PLCI_CONNECT_ACTIVE_IND	6	/* P-1 -> P-ACT */
+#define EV_PLCI_CONNECT_REQ		1	/* P-0 -> P-0.1
+                                                 */
+#define EV_PLCI_CONNECT_CONF_ERROR	2	/* P-0.1 -> P-0
+                                                 */
+#define EV_PLCI_CONNECT_CONF_OK		3	/* P-0.1 -> P-1
+                                                 */
+#define EV_PLCI_FACILITY_IND_UP		4	/* P-0 -> P-1
+                                                 */
+#define EV_PLCI_CONNECT_IND		5	/* P-0 -> P-2
+                                                 */
+#define EV_PLCI_CONNECT_ACTIVE_IND	6	/* P-1 -> P-ACT
+                                                 */
X #define EV_PLCI_CONNECT_REJECT		7	/* P-2 -> P-5
-						   P-3 -> P-5 */
+						   P-3 -> P-5
+						 */
X #define EV_PLCI_DISCONNECT_REQ		8	/* P-1 -> P-5
X 						   P-2 -> P-5
X 						   P-3 -> P-5
X 						   P-4 -> P-5
-						   P-ACT -> P-5 */
+						   P-ACT -> P-5
+						   P-Res -> P-5 (*)
+						   P-HELD -> P-5 (*)
+						   */
X #define EV_PLCI_DISCONNECT_IND		9	/* P-1 -> P-6
X 						   P-2 -> P-6
X 						   P-3 -> P-6
X 						   P-4 -> P-6
X 						   P-5 -> P-6
-						   P-ACT -> P-6 */
+						   P-ACT -> P-6
+						   P-Res -> P-6 (*)
+						   P-HELD -> P-6 (*)
+						   */
X #define EV_PLCI_FACILITY_IND_DOWN	10	/* P-0.1 -> P-5
X 						   P-1 -> P-5
X 						   P-ACT -> P-5
X 						   P-2 -> P-5
X 						   P-3 -> P-5
-						   P-4 -> P-5 */
-#define EV_PLCI_DISCONNECT_RESP		11	/* P-6 -> P-0 */
-#define EV_PLCI_CONNECT_RESP		12	/* P-6 -> P-0 */
+						   P-4 -> P-5
+						   */
+#define EV_PLCI_DISCONNECT_RESP		11	/* P-6 -> P-0
+                                                   */
+#define EV_PLCI_CONNECT_RESP		12	/* P-6 -> P-0
+                                                   */
+
+#define EV_PLCI_RESUME_REQ		13	/* P-0 -> P-0.Res
+                                                 */
+#define EV_PLCI_RESUME_CONF_OK		14	/* P-0.Res -> P-Res
+                                                 */
+#define EV_PLCI_RESUME_CONF_ERROR	15	/* P-0.Res -> P-0
+                                                 */
+#define EV_PLCI_RESUME_IND		16	/* P-Res -> P-ACT
+                                                 */
+#define EV_PLCI_HOLD_IND		17	/* P-ACT -> P-HELD
+                                                 */
+#define EV_PLCI_RETRIEVE_IND		18	/* P-HELD -> P-ACT
+                                                 */
+#define EV_PLCI_SUSPEND_IND		19	/* P-ACT -> P-5
+                                                 */
+#define EV_PLCI_CD_IND			20	/* P-2 -> P-5
+                                                 */
X 
X /*
X  * per ncci state machine
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/compat.h linux/drivers/isdn/avmb1/compat.h
--- v2.3.3/linux/drivers/isdn/avmb1/compat.h	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/avmb1/compat.h	Sun May 23 10:03:41 1999
@@ -1,11 +1,14 @@
X /*
- * $Id: compat.h,v 1.3 1997/11/04 06:12:15 calle Exp $
+ * $Id: compat.h,v 1.4 1998/10/25 14:39:02 fritz Exp $
X  * 
X  * Headerfile for Compartibility between different kernel versions
X  * 
X  * (c) Copyright 1996 by Carsten Paeth (ca...@calle.in-berlin.de)
X  * 
X  * $Log: compat.h,v $
+ * Revision 1.4  1998/10/25 14:39:02  fritz
+ * Backported from MIPS (Cobalt).
+ *
X  * Revision 1.3  1997/11/04 06:12:15  calle
X  * capi.c: new read/write in file_ops since 2.1.60
X  * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
@@ -32,6 +35,7 @@
X #define __COMPAT_H__
X 
X #include <linux/version.h>
+#include <asm/segment.h>
X #include <linux/isdnif.h>
X 
X #ifndef LinuxVersionCode
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/eicon/Makefile linux/drivers/isdn/eicon/Makefile
--- v2.3.3/linux/drivers/isdn/eicon/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/eicon/Makefile	Sun May 23 10:03:41 1999
@@ -0,0 +1,13 @@
+L_OBJS :=
+M_OBJS :=
+O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
+
+O_TARGET :=
+ifeq ($(CONFIG_ISDN_DRV_EICON),y)
+  O_TARGET += eicon.o
+else
+  O_TARGET += eicon.o
+  M_OBJS   = eicon.o
+endif
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- v2.3.3/linux/drivers/isdn/eicon/eicon.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/eicon/eicon.h	Sun May 23 10:03:41 1999
@@ -0,0 +1,528 @@
+/* $Id: eicon.h,v 1.5 1999/03/29 11:19:41 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ *
+ * Copyright 1998    by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998,99 by Armin Schindler (m...@melware.de) 
+ * Copyright 1999    Cytronics & Melware (in...@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon.h,v $
+ * Revision 1.5  1999/03/29 11:19:41  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.4  1999/03/02 12:37:42  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.3  1999/01/24 20:14:07  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.2  1999/01/10 18:46:04  armin
+ * Bug with wrong values in HLC fixed.
+ * Bytes to send are counted and limited now.
+ *
+ * Revision 1.1  1999/01/01 18:09:41  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+
+#ifndef eicon_h
+#define eicon_h
+
+#define EICON_IOCTL_SETMMIO   0
+#define EICON_IOCTL_GETMMIO   1
+#define EICON_IOCTL_SETIRQ    2
+#define EICON_IOCTL_GETIRQ    3
+#define EICON_IOCTL_LOADBOOT  4
+#define EICON_IOCTL_ADDCARD   5
+#define EICON_IOCTL_GETTYPE   6
+#define EICON_IOCTL_LOADPCI   7 
+#define EICON_IOCTL_LOADISA   8 
+#define EICON_IOCTL_GETVER    9 
+
+#define EICON_IOCTL_MANIF    90 
+
+#define EICON_IOCTL_FREEIT   97
+#define EICON_IOCTL_TEST     98
+#define EICON_IOCTL_DEBUGVAR 99
+
+/* Bus types */
+#define EICON_BUS_ISA          1
+#define EICON_BUS_MCA          2
+#define EICON_BUS_PCI          3
+
+/* Constants for describing Card-Type */
+#define EICON_CTYPE_S            0
+#define EICON_CTYPE_SX           1
+#define EICON_CTYPE_SCOM         2
+#define EICON_CTYPE_QUADRO       3
+#define EICON_CTYPE_S2M          4
+#define EICON_CTYPE_MAESTRA      5
+#define EICON_CTYPE_MAESTRAQ     6
+#define EICON_CTYPE_MAESTRAQ_U   7
+#define EICON_CTYPE_MAESTRAP     8
+#define EICON_CTYPE_ISABRI       0x10
+#define EICON_CTYPE_ISAPRI       0x20
+#define EICON_CTYPE_MASK         0x0f
+#define EICON_CTYPE_QUADRO_NR(n) (n<<4)
+
+#define MAX_HEADER_LEN 10
+
+/* Struct for adding new cards */
+typedef struct eicon_cdef {
+        int membase;
+        int irq;
+        char id[10];
+} eicon_cdef;
+
+#define EICON_ISA_BOOT_MEMCHK 1
+#define EICON_ISA_BOOT_NORMAL 2
+
+/* Struct for downloading protocol via ioctl for ISA cards */
+typedef struct {
+	/* start-up parameters */
+	unsigned char tei;
+	unsigned char nt2;
+	unsigned char skip1;
+	unsigned char WatchDog;
+	unsigned char Permanent;
+	unsigned char XInterface;
+	unsigned char StableL2;
+	unsigned char NoOrderCheck;
+	unsigned char HandsetType;
+	unsigned char skip2;
+	unsigned char LowChannel;
+	unsigned char ProtVersion;
+	unsigned char Crc4;
+	unsigned char Loopback;
+	unsigned char oad[32];
+	unsigned char osa[32];
+	unsigned char spid[32];
+	unsigned char boot_opt;
+	unsigned long bootstrap_len;
+	unsigned long firmware_len;
+	unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */
+} eicon_isa_codebuf;
+
+/* Struct for downloading protocol via ioctl for PCI cards */
+typedef struct {
+        /* start-up parameters */
+        unsigned char tei;
+        unsigned char nt2;
+        unsigned char WatchDog;
+        unsigned char Permanent;
+        unsigned char XInterface;
+        unsigned char StableL2;
+        unsigned char NoOrderCheck;
+        unsigned char HandsetType;
+        unsigned char LowChannel;
+        unsigned char ProtVersion;
+        unsigned char Crc4;
+        unsigned char NoHscx30Mode;  /* switch PRI into No HSCX30 test mode */
+        unsigned char Loopback;      /* switch card into Loopback mode */
+        struct q931_link_s
+        {
+          unsigned char oad[32];
+          unsigned char osa[32];
+          unsigned char spid[32];
+        } l[2];
+        unsigned long protocol_len;
+	unsigned int  dsp_code_num;
+        unsigned long dsp_code_len[9];
+        unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */
+} eicon_pci_codebuf;
+
+/* Data for downloading protocol via ioctl */
+typedef union {
+	eicon_isa_codebuf isa;
+	eicon_pci_codebuf pci;
+} eicon_codebuf;
+
+/* Data for Management interface */
+typedef struct {
+	int count;
+	int pos;
+	int length[50];
+	unsigned char data[700]; 
+} eicon_manifbuf;
+
+
+#ifdef __KERNEL__
+
+/* Kernel includes */
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+#include <linux/isdnif.h>
+
+typedef struct {
+  __u16 length __attribute__ ((packed)); /* length of data/parameter field */
+  __u8  P[1];                          /* data/parameter field */
+} eicon_PBUFFER;
+
+#include "eicon_isa.h"
+
+/* Macro for delay via schedule() */
+#define SLEEP(j) {                     \
+  current->state = TASK_INTERRUPTIBLE; \
+  schedule_timeout(j);                 \
+}
+
+#endif /* KERNEL */
+
+
+#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
+#define DSP_COMBIFILE_FORMAT_VERSION_BCD    0x0100
+
+#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
+#define DSP_FILE_FORMAT_VERSION_BCD         0x0100
+
+typedef struct tag_dsp_combifile_header
+{
+  char                  format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
+  __u16                  format_version_bcd             __attribute__ ((packed));
+  __u16                  header_size                    __attribute__ ((packed));
+  __u16                  combifile_description_size     __attribute__ ((packed));
+  __u16                  directory_entries              __attribute__ ((packed));
+  __u16                  directory_size                 __attribute__ ((packed));
+  __u16                  download_count                 __attribute__ ((packed));
+  __u16                  usage_mask_size                __attribute__ ((packed));
+} t_dsp_combifile_header;
+
+typedef struct tag_dsp_combifile_directory_entry
+{
+  __u16                  card_type_number               __attribute__ ((packed));
+  __u16                  file_set_number                __attribute__ ((packed));
+} t_dsp_combifile_directory_entry;
+
+typedef struct tag_dsp_file_header
+{
+  char                  format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
+  __u16                 format_version_bcd              __attribute__ ((packed));
+  __u16                 download_id                     __attribute__ ((packed));
+  __u16                 download_flags                  __attribute__ ((packed));
+  __u16                 required_processing_power       __attribute__ ((packed));
+  __u16                 interface_channel_count         __attribute__ ((packed));
+  __u16                 header_size                     __attribute__ ((packed));
+  __u16                 download_description_size       __attribute__ ((packed));
+  __u16                 memory_block_table_size         __attribute__ ((packed));
+  __u16                 memory_block_count              __attribute__ ((packed));
+  __u16                 segment_table_size              __attribute__ ((packed));
+  __u16                 segment_count                   __attribute__ ((packed));
+  __u16                 symbol_table_size               __attribute__ ((packed));
+  __u16                 symbol_count                    __attribute__ ((packed));
+  __u16                 total_data_size_dm              __attribute__ ((packed));
+  __u16                 data_block_count_dm             __attribute__ ((packed));
+  __u16                 total_data_size_pm              __attribute__ ((packed));
+  __u16                 data_block_count_pm             __attribute__ ((packed));
+} t_dsp_file_header;
+
+typedef struct tag_dsp_memory_block_desc
+{
+  __u16                 alias_memory_block;
+  __u16                 memory_type;
+  __u16                 address;
+  __u16                 size;             /* DSP words */
+} t_dsp_memory_block_desc;
+
+typedef struct tag_dsp_segment_desc
+{
+  __u16                 memory_block;
+  __u16                 attributes;
+  __u16                 base;
+  __u16                 size;
+  __u16                 alignment;        /* ==0 -> no other legal start address than base */
+} t_dsp_segment_desc;
+
+typedef struct tag_dsp_symbol_desc
+{
+  __u16                 symbol_id;
+  __u16                 segment;
+  __u16                 offset;
+  __u16                 size;             /* DSP words */
+} t_dsp_symbol_desc;
+
+typedef struct tag_dsp_data_block_header
+{
+  __u16                 attributes;
+  __u16                 segment;
+  __u16                 offset;
+  __u16                 size;             /* DSP words */
+} t_dsp_data_block_header;
+
+typedef struct tag_dsp_download_desc      /* be sure to keep native alignment for MAESTRA's */
+{
+  __u16                 download_id;
+  __u16                 download_flags;
+  __u16                 required_processing_power;
+  __u16                 interface_channel_count;
+  __u16                 excess_header_size;
+  __u16                 memory_block_count;
+  __u16                 segment_count;
+  __u16                 symbol_count;
+  __u16                 data_block_count_dm;
+  __u16                 data_block_count_pm;
+  __u8  *            p_excess_header_data               __attribute__ ((packed));
+  char  *            p_download_description             __attribute__ ((packed));
+  t_dsp_memory_block_desc  *p_memory_block_table        __attribute__ ((packed));
+  t_dsp_segment_desc  *p_segment_table                  __attribute__ ((packed));
+  t_dsp_symbol_desc  *p_symbol_table                    __attribute__ ((packed));
+  __u16 *            p_data_blocks_dm                   __attribute__ ((packed));
+  __u16 *            p_data_blocks_pm                   __attribute__ ((packed));
+} t_dsp_download_desc;
+
+
+#ifdef __KERNEL__
+
+typedef struct {
+  __u8                  Req;            /* pending request          */
+  __u8                  Rc;             /* return code received     */
+  __u8                  Ind;            /* indication received      */
+  __u8                  ReqCh;          /* channel of current Req   */
+  __u8                  RcCh;           /* channel of current Rc    */
+  __u8                  IndCh;          /* channel of current Ind   */
+  __u8                  D3Id;           /* ID used by this entity   */
+  __u8                  B2Id;           /* ID used by this entity   */
+  __u8                  GlobalId;       /* reserved field           */
+  __u8                  XNum;           /* number of X-buffers      */
+  __u8                  RNum;           /* number of R-buffers      */
+  struct sk_buff_head   X;              /* X-buffer queue           */
+  struct sk_buff_head   R;              /* R-buffer queue           */
+  __u8                  RNR;            /* receive not ready flag   */
+  __u8                  complete;       /* receive complete status  */
+  __u8                  busy;           /* busy flag                */
+  __u16                 ref;            /* saved reference          */
+} entity;
+
+
+typedef struct {
+	int	       No;		 /* Channel Number	        */
+	unsigned short callref;          /* Call Reference              */
+	unsigned short fsm_state;        /* Current D-Channel state     */
+	unsigned short eazmask;          /* EAZ-Mask for this Channel   */
+	unsigned int   queued;           /* User-Data Bytes in TX queue */
+	unsigned int   waitq;            /* User-Data Bytes in wait queue */
+	unsigned int   waitpq;           /* User-Data Bytes in packet queue */
+	unsigned short plci;
+	unsigned short ncci;
+	unsigned char  l2prot;           /* Layer 2 protocol            */
+	unsigned char  l3prot;           /* Layer 3 protocol            */
+	entity		e;		 /* Entity  			*/
+	char		cpn[32];	 /* remember cpn		*/
+	char		oad[32];	 /* remember oad		*/
+	unsigned char   cause[2];	 /* Last Cause			*/
+	unsigned char	si1;
+	unsigned char	si2;
+} eicon_chan;
+
+typedef struct {
+	eicon_chan *ptr;
+} eicon_chan_ptr;
+
+#include "eicon_pci.h"
+
+#define EICON_FLAGS_RUNNING  1 /* Cards driver activated */
+#define EICON_FLAGS_PVALID   2 /* Cards port is valid    */
+#define EICON_FLAGS_IVALID   4 /* Cards irq is valid     */
+#define EICON_FLAGS_MVALID   8 /* Cards membase is valid */
+#define EICON_FLAGS_LOADED   8 /* Firmware loaded        */
+
+#define EICON_BCH            2 /* # of channels per card */
+
+/* D-Channel states */
+#define EICON_STATE_NULL     0
+#define EICON_STATE_ICALL    1
+#define EICON_STATE_OCALL    2
+#define EICON_STATE_IWAIT    3
+#define EICON_STATE_OWAIT    4
+#define EICON_STATE_IBWAIT   5
+#define EICON_STATE_OBWAIT   6
+#define EICON_STATE_BWAIT    7
+#define EICON_STATE_BHWAIT   8
+#define EICON_STATE_BHWAIT2  9
+#define EICON_STATE_DHWAIT  10
+#define EICON_STATE_DHWAIT2 11
+#define EICON_STATE_BSETUP  12
+#define EICON_STATE_ACTIVE  13
+#define EICON_STATE_ICALLW  14
+#define EICON_STATE_LISTEN  15
+#define EICON_STATE_WMCONN  16
+
+#define EICON_MAX_QUEUED  8000 /* 2 * maxbuff */
+
+#define EICON_LOCK_TX 0
+#define EICON_LOCK_RX 1
+
+typedef struct {
+	int dummy;
+} eicon_mca_card;
+
+typedef union {
+	eicon_isa_card isa;
+	eicon_pci_card pci;
+	eicon_mca_card mca;
+} eicon_hwif;
+
+typedef struct {
+	__u8 ret;
+	__u8 id;
+	__u8 ch;
+} eicon_ack;
+
+typedef struct {
+	__u8 code;
+	__u8 id;
+	__u8 ch;
+} eicon_req;
+
+typedef struct {
+	__u8 ret;
+	__u8 id;
+	__u8 ch;
+	__u8 more;
+} eicon_indhdr;
+
+typedef struct msn_entry {
+	char eaz;
+        char msn[16];
+        struct msn_entry * next;
+} msn_entry;
+
+/*
+ * Per card driver data
+ */
+typedef struct eicon_card {
+	eicon_hwif hwif;                 /* Hardware dependant interface     */
+        u_char ptype;                    /* Protocol type (1TR6 or Euro)     */
+        u_char bus;                      /* Bustype (ISA, MCA, PCI)          */
+        u_char type;                     /* Cardtype (EICON_CTYPE_...)       */
+	struct eicon_card *qnext;  	 /* Pointer to next quadro adapter   */
+        int Feature;                     /* Protocol Feature Value           */
+        struct eicon_card *next;	 /* Pointer to next device struct    */
+        int myid;                        /* Driver-Nr. assigned by linklevel */
+        unsigned long flags;             /* Statusflags                      */
+        unsigned long ilock;             /* Semaphores for IRQ-Routines      */
+	struct sk_buff_head rcvq;        /* Receive-Message queue            */
+	struct sk_buff_head sndq;        /* Send-Message queue               */
+	struct sk_buff_head rackq;       /* Req-Ack-Message queue            */
+	struct sk_buff_head sackq;       /* Data-Ack-Message queue           */
+	u_char *ack_msg;                 /* Ptr to User Data in User skb     */
+	__u16 need_b3ack;                /* Flag: Need ACK for current skb   */
+	struct sk_buff *sbuf;            /* skb which is currently sent      */
+	struct tq_struct snd_tq;         /* Task struct for xmit bh          */
+	struct tq_struct rcv_tq;         /* Task struct for rcv bh           */
+	struct tq_struct ack_tq;         /* Task struct for ack bh           */
+	msn_entry *msn_list;
+	unsigned short msgnum;           /* Message number for sending       */
+	eicon_chan*	IdTable[256];	 /* Table to find entity   */
+	__u16  ref_in;
+	__u16  ref_out;
+	int    nchannels;                /* Number of B-Channels             */
+	int    ReadyInt;		 /* Ready Interrupt		     */
+	eicon_chan *bch;                 /* B-Channel status/control         */
+	char   status_buf[256];          /* Buffer for status messages       */
+	char   *status_buf_read;
+	char   *status_buf_write;
+	char   *status_buf_end;
+        isdn_if interface;               /* Interface to upper layer         */
+        char regname[35];                /* Name used for request_region     */
+} eicon_card;
+
+/* -----------------------------------------------------------**
+** The PROTOCOL_FEATURE_STRING                                **
+** defines capabilities and                                   **
+** features of the actual protocol code. It's used as a bit   **
+** mask.                                                      **
+** The following Bits are defined:                            **
+** -----------------------------------------------------------*/
+#define PROTCAP_TELINDUS  0x0001  /* Telindus Variant of protocol code   */
+#define PROTCAP_MANIF     0x0002  /* Management interface implemented    */
+#define PROTCAP_V_42      0x0004  /* V42 implemented                     */
+#define PROTCAP_V90D      0x0008  /* V.90D (implies up to 384k DSP code) */
+#define PROTCAP_EXTD_FAX  0x0010  /* Extended FAX (ECM, 2D, T6, Polling) */
+#define PROTCAP_FREE4     0x0020  /* not used                            */
+#define PROTCAP_FREE5     0x0040  /* not used                            */
+#define PROTCAP_FREE6     0x0080  /* not used                            */
+#define PROTCAP_FREE7     0x0100  /* not used                            */
+#define PROTCAP_FREE8     0x0200  /* not used                            */
+#define PROTCAP_FREE9     0x0400  /* not used                            */
+#define PROTCAP_FREE10    0x0800  /* not used                            */
+#define PROTCAP_FREE11    0x1000  /* not used                            */
+#define PROTCAP_FREE12    0x2000  /* not used                            */
+#define PROTCAP_FREE13    0x4000  /* not used                            */
+#define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
+
+#include "eicon_idi.h"
+
+extern eicon_card *cards;
+extern char *eicon_ctype_name[];
+
+
+extern __inline__ void eicon_schedule_tx(eicon_card *card)
+{
+        queue_task(&card->snd_tq, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+extern __inline__ void eicon_schedule_rx(eicon_card *card)
+{
+        queue_task(&card->rcv_tq, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+extern __inline__ void eicon_schedule_ack(eicon_card *card)
+{
+        queue_task(&card->ack_tq, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+extern char *eicon_find_eaz(eicon_card *, char);
+extern int eicon_addcard(int, int, int, char *);
+extern void eicon_io_transmit(eicon_card *card);
+extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
+extern void eicon_io_rcv_dispatch(eicon_card *ccard);
+extern void eicon_io_ack_dispatch(eicon_card *ccard);
+extern ulong DebugVar;
+
+#endif  /* __KERNEL__ */
+
+#endif	/* eicon_h */
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/eicon/eicon_dsp.h linux/drivers/isdn/eicon/eicon_dsp.h
--- v2.3.3/linux/drivers/isdn/eicon/eicon_dsp.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/eicon/eicon_dsp.h	Sun May 23 10:03:41 1999
@@ -0,0 +1,304 @@
+/* $Id: eicon_dsp.h,v 1.2 1999/03/29 11:19:42 armin Exp $
+ *
+ * ISDN lowlevel-module for Eicon.Diehl active cards.
+ *        DSP definitions
+ *
+ * Copyright 1999    by Armin Schindler (m...@melware.de)
+ * Copyright 1999    Cytronics & Melware (in...@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: eicon_dsp.h,v $
+ * Revision 1.2  1999/03/29 11:19:42  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.1  1999/03/02 12:18:54  armin
+ * First checkin of DSP defines for audio features.
+ *
+ *
+ */
+
+#ifndef DSP_H
+#define DSP_H
+
+#define DSP_UDATA_REQUEST_RECONFIGURE           0
+/*
+parameters:
+  <word> reconfigure delay (in 8kHz samples)
+  <word> reconfigure code
+  <byte> reconfigure hdlc preamble flags
+*/
+
+#define DSP_RECONFIGURE_TX_FLAG             0x8000
+#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG    0x4000
+#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG   0x2000
+#define DSP_RECONFIGURE_HDLC_FLAG           0x1000
+#define DSP_RECONFIGURE_SYNC_FLAG           0x0800
+#define DSP_RECONFIGURE_PROTOCOL_MASK       0x00ff
+#define DSP_RECONFIGURE_IDLE                0
+#define DSP_RECONFIGURE_V25                 1
+#define DSP_RECONFIGURE_V21_CH2             2
+#define DSP_RECONFIGURE_V27_2400            3
+#define DSP_RECONFIGURE_V27_4800            4
+#define DSP_RECONFIGURE_V29_7200            5
+#define DSP_RECONFIGURE_V29_9600            6
+#define DSP_RECONFIGURE_V33_12000           7
+#define DSP_RECONFIGURE_V33_14400           8
+#define DSP_RECONFIGURE_V17_7200            9
+#define DSP_RECONFIGURE_V17_9600            10
+#define DSP_RECONFIGURE_V17_12000           11
+#define DSP_RECONFIGURE_V17_14400           12
+
+/*
+data indications if transparent framer
+  <byte> data 0
+  <byte> data 1
+  ...
+
+data indications if HDLC framer
+  <byte> data 0
+  <byte> data 1
+  ...
+  <byte> CRC 0
+  <byte> CRC 1
+  <byte> preamble flags
+*/
+
+#define DSP_UDATA_REQUEST_SWITCH_FRAMER         1
+/*
+parameters:
+  <byte> transmit framer type
+  <byte> receive framer type
+*/
+
+#define DSP_REQUEST_SWITCH_FRAMER_HDLC          0
+#define DSP_REQUEST_SWITCH_FRAMER_TRANSPARENT   1
+#define DSP_REQUEST_SWITCH_FRAMER_ASYNC         2
+
+
+#define DSP_UDATA_REQUEST_CLEARDOWN             2
+/*
+parameters:
+  - none -
+*/
+
+
+#define DSP_UDATA_REQUEST_TX_CONFIRMATION_ON    3
+/*
+parameters:
+  - none -
+*/
+
+
+#define DSP_UDATA_REQUEST_TX_CONFIRMATION_OFF   4
+/*
+parameters:
+  - none -
+*/
+
+
+#define DSP_UDATA_INDICATION_SYNC               0
+/*
+returns:
+  <word> time of sync (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_DCD_OFF            1
+/*
+returns:
+  <word> time of DCD off (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_DCD_ON             2
+/*
+returns:
+  <word> time of DCD on (sampled from counter at 8kHz)
+  <byte> connected norm
+  <word> connected options
+  <dword> connected speed (bit/s, max of tx and rx speed)
+  <word> roundtrip delay (ms)
+  <dword> connected speed tx (bit/s)
+  <dword> connected speed rx (bit/s)
+*/
+
+#define DSP_UDATA_INDICATION_CTS_OFF            3
+/*
+returns:
+  <word> time of CTS off (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_CTS_ON             4
+/*
+returns:
+  <word> time of CTS on (sampled from counter at 8kHz)
+  <byte> connected norm
+  <word> connected options
+  <dword> connected speed (bit/s, max of tx and rx speed)
+  <word> roundtrip delay (ms)
+  <dword> connected speed tx (bit/s)
+  <dword> connected speed rx (bit/s)
+*/
+
+typedef struct eicon_dsp_ind {
+	__u16	time		__attribute__ ((packed));
+	__u8	norm		__attribute__ ((packed));
+	__u16	options		__attribute__ ((packed));
+	__u32	speed		__attribute__ ((packed));
+	__u16	delay		__attribute__ ((packed));
+	__u32	txspeed		__attribute__ ((packed));
+	__u32	rxspeed		__attribute__ ((packed));
+} eicon_dsp_ind;
+
+#define DSP_CONNECTED_NORM_UNSPECIFIED      0
+#define DSP_CONNECTED_NORM_V21              1
+#define DSP_CONNECTED_NORM_V23              2
+#define DSP_CONNECTED_NORM_V22              3
+#define DSP_CONNECTED_NORM_V22_BIS          4
+#define DSP_CONNECTED_NORM_V32_BIS          5
+#define DSP_CONNECTED_NORM_V34              6
+#define DSP_CONNECTED_NORM_V8               7
+#define DSP_CONNECTED_NORM_BELL_212A        8
+#define DSP_CONNECTED_NORM_BELL_103         9
+#define DSP_CONNECTED_NORM_V29_LEASED_LINE  10
+#define DSP_CONNECTED_NORM_V33_LEASED_LINE  11
+#define DSP_CONNECTED_NORM_V90              12
+#define DSP_CONNECTED_NORM_V21_CH2          13
+#define DSP_CONNECTED_NORM_V27_TER          14
+#define DSP_CONNECTED_NORM_V29              15
+#define DSP_CONNECTED_NORM_V33              16
+#define DSP_CONNECTED_NORM_V17              17
+
+#define DSP_CONNECTED_OPTION_TRELLIS             0x0001
+#define DSP_CONNECTED_OPTION_V42_TRANS           0x0002
+#define DSP_CONNECTED_OPTION_V42_LAPM            0x0004
+#define DSP_CONNECTED_OPTION_SHORT_TRAIN         0x0008
+#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
+
+
+#define DSP_UDATA_INDICATION_DISCONNECT         5
+/*
+returns:
+  <byte> cause
+*/
+
+#define DSP_DISCONNECT_CAUSE_NONE               0x00
+#define DSP_DISCONNECT_CAUSE_BUSY_TONE          0x01
+#define DSP_DISCONNECT_CAUSE_CONGESTION_TONE    0x02
+#define DSP_DISCONNECT_CAUSE_INCOMPATIBILITY    0x03
+#define DSP_DISCONNECT_CAUSE_CLEARDOWN          0x04
+#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT   0x05
+
+
+#define DSP_UDATA_INDICATION_TX_CONFIRMATION    6
+/*
+returns:
+  <word> confirmation number
+*/
+
+
+#define DSP_UDATA_REQUEST_SEND_DTMF_DIGITS      16
+/*
+parameters:
+  <word> tone duration (ms)
+  <word> gap duration (ms)
+  <byte> digit 0 tone code
+  ...
+  <byte> digit n tone code
+*/
+
+#define DSP_SEND_DTMF_DIGITS_HEADER_LENGTH      5
+
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_697_HZ    0x00
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_770_HZ    0x01
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_852_HZ    0x02
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_941_HZ    0x03
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_MASK      0x03
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ  0x00
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ  0x04
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ  0x08
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ  0x0c
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_MASK     0x0c
+
+#define DSP_DTMF_DIGIT_TONE_CODE_0              0x07
+#define DSP_DTMF_DIGIT_TONE_CODE_1              0x00
+#define DSP_DTMF_DIGIT_TONE_CODE_2              0x04
+#define DSP_DTMF_DIGIT_TONE_CODE_3              0x08
+#define DSP_DTMF_DIGIT_TONE_CODE_4              0x01
+#define DSP_DTMF_DIGIT_TONE_CODE_5              0x05
+#define DSP_DTMF_DIGIT_TONE_CODE_6              0x09
+#define DSP_DTMF_DIGIT_TONE_CODE_7              0x02
+#define DSP_DTMF_DIGIT_TONE_CODE_8              0x06
+#define DSP_DTMF_DIGIT_TONE_CODE_9              0x0a
+#define DSP_DTMF_DIGIT_TONE_CODE_STAR           0x03
+#define DSP_DTMF_DIGIT_TONE_CODE_HASHMARK       0x0b
+#define DSP_DTMF_DIGIT_TONE_CODE_A              0x0c
+#define DSP_DTMF_DIGIT_TONE_CODE_B              0x0d
+#define DSP_DTMF_DIGIT_TONE_CODE_C              0x0e
+#define DSP_DTMF_DIGIT_TONE_CODE_D              0x0f
+
+
+#define DSP_UDATA_INDICATION_DTMF_DIGITS_SENT   16
+/*
+returns:
+  - none -
+  One indication will be sent for every request.
+*/
+
+
+#define DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER  17
+/*
+parameters:
+  <word> tone duration (ms)
+  <word> gap duration (ms)
+*/
+
+#define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18
+/*
+parameters:
+  - none -
+*/
+
+#define DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17
+/*
+returns:
+  <byte> digit 0 tone code
+  ...
+  <byte> digit n tone code
+*/
+
+#define DSP_DTMF_DIGITS_RECEIVED_HEADER_LENGTH  1
+
+
+#define DSP_UDATA_INDICATION_MODEM_CALLING_TONE 18
+/*
+returns:
+  - none -
+*/
+
+#define DSP_UDATA_INDICATION_FAX_CALLING_TONE   19
+/*
+returns:
+  - none -
+*/
+
+#define DSP_UDATA_INDICATION_ANSWER_TONE        20
+/*
+returns:
+  - none -
+*/
+
+#endif	/* DSP_H */
+
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- v2.3.3/linux/drivers/isdn/eicon/eicon_idi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/eicon/eicon_idi.c	Sun May 23 10:03:41 1999
@@ -0,0 +1,1479 @@
+/* $Id: eicon_idi.c,v 1.9 1999/03/29 11:19:42 armin Exp $
+ *
+ * ISDN lowlevel-module for Eicon.Diehl active cards.
+ *        IDI interface 
+ *
+ * Copyright 1998,99 by Armin Schindler (m...@melware.de)
+ * Copyright 1999    Cytronics & Melware (in...@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_idi.c,v $
+ * Revision 1.9  1999/03/29 11:19:42  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.8  1999/03/02 12:37:43  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.7  1999/02/03 18:34:35  armin
+ * Channel selection for outgoing calls w/o CHI.
+ * Added channel # in debug messages.
+ * L2 Transparent should work with 800 byte/packet now.
+ *
+ * Revision 1.6  1999/01/26 07:18:59  armin
+ * Bug with wrong added CPN fixed.
+ *
+ * Revision 1.5  1999/01/24 20:14:11  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.4  1999/01/10 18:46:05  armin
+ * Bug with wrong values in HLC fixed.
+ * Bytes to send are counted and limited now.
+ *
+ * Revision 1.3  1999/01/05 14:49:34  armin
+ * Added experimental usage of full BC and HLC for
+ * speech, 3.1kHz audio, fax gr.2/3
+ *
+ * Revision 1.2  1999/01/04 13:19:29  armin
+ * Channel status with listen-request wrong - fixed.
+ *
+ * Revision 1.1  1999/01/01 18:09:41  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "eicon.h"
+#include "eicon_idi.h"
+#include "eicon_dsp.h"
+
+#undef EICON_FULL_SERVICE_OKTETT
+
+char *eicon_idi_revision = "$Revision: 1.9 $";
+
+eicon_manifbuf *manbuf;
+
+static char BC_Speech[3] = 	{ 0x80, 0x90, 0xa3 };
+static char BC_31khz[3] =  	{ 0x90, 0x90, 0xa3 };
+static char BC_64k[2] =    	{ 0x88, 0x90 };
+static char BC_video[3] =  	{ 0x91, 0x90, 0xa5 };
+
+#ifdef EICON_FULL_SERVICE_OKTETT
+/* 
+static char HLC_telephony[2] =	{ 0x91, 0x81 }; 
+*/
+static char HLC_faxg3[2] =  	{ 0x91, 0x84 };
+#endif
+
+int eicon_idi_manage_assign(eicon_card *card);
+int eicon_idi_manage_remove(eicon_card *card);
+
+int
+idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
+{
+	int l = 0;
+  if (!signet) {
+	/* Signal Layer */
+	reqbuf->XBuffer.P[l++] = CAI;
+	reqbuf->XBuffer.P[l++] = 1;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = KEY;
+	reqbuf->XBuffer.P[l++] = 3;
+	reqbuf->XBuffer.P[l++] = 'I';
+	reqbuf->XBuffer.P[l++] = '4';
+	reqbuf->XBuffer.P[l++] = 'L';
+	reqbuf->XBuffer.P[l++] = SHIFT|6;
+	reqbuf->XBuffer.P[l++] = SIN;
+	reqbuf->XBuffer.P[l++] = 2;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0; /* end */
+	reqbuf->Req = ASSIGN;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 0;
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 0; /* Sig Entity */
+  }
+  else {
+	/* Network Layer */
+	reqbuf->XBuffer.P[l++] = CAI;
+	reqbuf->XBuffer.P[l++] = 1;
+	reqbuf->XBuffer.P[l++] = chan->e.D3Id;
+	reqbuf->XBuffer.P[l++] = LLC;
+	reqbuf->XBuffer.P[l++] = 2;
+	switch(chan->l2prot) {
+		case ISDN_PROTO_L2_HDLC:
+			reqbuf->XBuffer.P[l++] = 2;
+			break;
+		case ISDN_PROTO_L2_X75I:
+		case ISDN_PROTO_L2_X75UI:
+		case ISDN_PROTO_L2_X75BUI:
+			reqbuf->XBuffer.P[l++] = 5; 
+			break;
+		case ISDN_PROTO_L2_TRANS:
+		case ISDN_PROTO_L2_MODEM:
+			reqbuf->XBuffer.P[l++] = 2;
+			break;
+		default:
+			reqbuf->XBuffer.P[l++] = 1;
+	}
+	switch(chan->l3prot) {
+		case ISDN_PROTO_L3_TRANS:
+		default:
+			reqbuf->XBuffer.P[l++] = 4;
+	}
+	reqbuf->XBuffer.P[l++] = 0; /* end */
+	reqbuf->Req = ASSIGN;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 0x20;
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 1; /* Net Entity */
+  }
+   return(0);
+}
+
+int
+idi_put_req(eicon_REQ *reqbuf, int rq, int signet)
+{
+	reqbuf->Req = rq;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+	reqbuf->XBuffer.length = 1;
+	reqbuf->XBuffer.P[0] = 0;
+	reqbuf->Reference = signet;
+   return(0);
+}
+
+int
+idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
+{
+	int l = 9;
+	reqbuf->Req = CALL_RES;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+	reqbuf->XBuffer.P[0] = CAI;
+	reqbuf->XBuffer.P[1] = 6;
+	reqbuf->XBuffer.P[2] = 9;
+	reqbuf->XBuffer.P[3] = 0;
+	reqbuf->XBuffer.P[4] = 0;
+	reqbuf->XBuffer.P[5] = 0;
+	reqbuf->XBuffer.P[6] = 32;
+	reqbuf->XBuffer.P[7] = 3;
+	switch(chan->l2prot) {
+		case ISDN_PROTO_L2_X75I:
+		case ISDN_PROTO_L2_X75UI:
+		case ISDN_PROTO_L2_X75BUI:
+		case ISDN_PROTO_L2_HDLC:
+			reqbuf->XBuffer.P[1] = 1;
+			reqbuf->XBuffer.P[2] = 0x05;
+			l = 4;
+			break;
+		case ISDN_PROTO_L2_V11096:
+			reqbuf->XBuffer.P[2] = 0x0d;
+			reqbuf->XBuffer.P[3] = 5;
+			reqbuf->XBuffer.P[4] = 0;
+			break;
+		case ISDN_PROTO_L2_V11019:
+			reqbuf->XBuffer.P[2] = 0x0d;
+			reqbuf->XBuffer.P[3] = 6;
+			reqbuf->XBuffer.P[4] = 0;
+			break;
+		case ISDN_PROTO_L2_V11038:
+			reqbuf->XBuffer.P[2] = 0x0d;
+			reqbuf->XBuffer.P[3] = 7;
+			reqbuf->XBuffer.P[4] = 0;
+			break;
+		case ISDN_PROTO_L2_MODEM:
+			reqbuf->XBuffer.P[2] = 0x11;
+			reqbuf->XBuffer.P[3] = 7;
+			reqbuf->XBuffer.P[4] = 0;
+			reqbuf->XBuffer.P[5] = 0;
+			reqbuf->XBuffer.P[6] = 128;
+			reqbuf->XBuffer.P[7] = 0;
+			break;
+	}
+	reqbuf->XBuffer.P[8] = 0;
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 0; /* Sig Entity */
+	if (DebugVar & 8)
+		printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No);
+   return(0);
+}
+
+int
+idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
+{
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+	eicon_REQ *reqbuf;
+	eicon_chan_ptr *chan2;
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                return -ENOMEM; 
+	}
+
+	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+	chan2->ptr = chan;
+
+	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+	if (DebugVar & 8)
+		printk(KERN_DEBUG "idi_req: Ch%d: 0x%02x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
+	if (layer) cmd |= 0x700;
+	switch(cmd) {
+		case ASSIGN:
+		case ASSIGN|0x700:
+			idi_assign_req(reqbuf, layer, chan);
+			break;
+		case REMOVE:
+		case REMOVE|0x700:
+			idi_put_req(reqbuf, REMOVE, layer);
+			break;
+		case INDICATE_REQ:
+			idi_put_req(reqbuf, INDICATE_REQ, 0);
+			break;
+		case HANGUP:
+			idi_put_req(reqbuf, HANGUP, 0);
+			break;
+		case REJECT:
+			idi_put_req(reqbuf, REJECT, 0);
+			break;
+		case CALL_ALERT:
+			idi_put_req(reqbuf, CALL_ALERT, 0);
+			break;
+		case CALL_RES:
+			idi_call_res_req(reqbuf, chan);
+			break;
+		case IDI_N_CONNECT|0x700:
+			idi_put_req(reqbuf, IDI_N_CONNECT, 1);
+			break;
+		case IDI_N_CONNECT_ACK|0x700:
+			idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1);
+			break;
+		case IDI_N_DISC|0x700:
+			idi_put_req(reqbuf, IDI_N_DISC, 1);
+			break;
+		case IDI_N_DISC_ACK|0x700:
+			idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
+			break;
+		default:
+			if (DebugVar & 1)
+				printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No);
+			return(-1);
+	}
+
+	skb_queue_tail(&chan->e.X, skb);
+	skb_queue_tail(&card->sndq, skb2); 
+	eicon_schedule_tx(card);
+	return(0);
+}
+
+int
+eicon_idi_listen_req(eicon_card *card, eicon_chan *chan)
+{
+	if (DebugVar & 16)
+		printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask);
+	if (!chan->e.D3Id) {
+		idi_do_req(card, chan, ASSIGN, 0); 
+	}
+	if (chan->fsm_state == EICON_STATE_NULL) {
+		idi_do_req(card, chan, INDICATE_REQ, 0);
+		chan->fsm_state = EICON_STATE_LISTEN;
+	}
+  return(0);
+}
+
+unsigned char
+idi_si2bc(int si1, int si2, char *bc, char *hlc)
+{
+  hlc[0] = 0;
+  switch(si1) {
+	case 1:
+		bc[0] = 0x90;		/* 3,1 kHz audio */
+		bc[1] = 0x90;		/* 64 kbit/s */
+		bc[2] = 0xa3;		/* G.711 A-law */
+#ifdef EICON_FULL_SERVICE_OKTETT
+		if (si2 == 1) {
+			bc[0] = 0x80;	/* Speech */
+			hlc[0] = 0x02;	/* hlc len */
+			hlc[1] = 0x91;	/* first hic */
+			hlc[2] = 0x81;	/* Telephony */
+		}
+#endif
+		return(3);
+	case 2:
+		bc[0] = 0x90;		/* 3,1 kHz audio */
+		bc[1] = 0x90;		/* 64 kbit/s */
+		bc[2] = 0xa3;		/* G.711 A-law */
+#ifdef EICON_FULL_SERVICE_OKTETT
+		if (si2 == 2) {
+			hlc[0] = 0x02;	/* hlc len */
+			hlc[1] = 0x91;	/* first hic */
+			hlc[2] = 0x84;	/* Fax Gr.2/3 */
+		}
+#endif
+		return(3);
+	case 5:
+	case 7:
+	default:
+		bc[0] = 0x88;
+		bc[1] = 0x90;
+		return(2);
+  }
+ return (0);
+}
+
+int
+idi_hangup(eicon_card *card, eicon_chan *chan)
+{
+	if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
+	    (chan->fsm_state == EICON_STATE_WMCONN)) {
+  		if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
+	}
+	if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
+	idi_do_req(card, chan, HANGUP, 0);
+	chan->fsm_state = EICON_STATE_NULL;
+	if (DebugVar & 8)
+		printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No);
+  return(0);
+}
+
+int
+idi_connect_res(eicon_card *card, eicon_chan *chan)
+{
+  chan->fsm_state = EICON_STATE_IWAIT;
+  idi_do_req(card, chan, CALL_RES, 0);
+  idi_do_req(card, chan, ASSIGN, 1);
+  return(0);
+}
+
+int
+idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
+                    char *eazmsn, int si1, int si2)
+{
+	int l = 0;
+	int i;
+	unsigned char tmp;
+	unsigned char bc[5];
+	unsigned char hlc[5];
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+	eicon_REQ *reqbuf;
+	eicon_chan_ptr *chan2;
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                return -ENOMEM; 
+	}
+
+	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+	chan2->ptr = chan;
+
+	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+	reqbuf->Req = CALL_REQ;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+
+	reqbuf->XBuffer.P[l++] = CPN;
+	reqbuf->XBuffer.P[l++] = strlen(phone) + 1;
+	reqbuf->XBuffer.P[l++] = 0xc1;
+	for(i=0; i<strlen(phone);i++) 
+		reqbuf->XBuffer.P[l++] = phone[i];
+
+	reqbuf->XBuffer.P[l++] = OAD;
+	reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2;
+	reqbuf->XBuffer.P[l++] = 0x01;
+	reqbuf->XBuffer.P[l++] = 0x81;
+	for(i=0; i<strlen(eazmsn);i++) 
+		reqbuf->XBuffer.P[l++] = eazmsn[i];
+
+	if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
+		reqbuf->XBuffer.P[l++] = BC;
+		reqbuf->XBuffer.P[l++] = tmp;
+		for(i=0; i<tmp;i++) 
+			reqbuf->XBuffer.P[l++] = bc[i];
+		if ((tmp=hlc[0])) {
+			reqbuf->XBuffer.P[l++] = HLC;
+			reqbuf->XBuffer.P[l++] = tmp;
+			for(i=1; i<=tmp;i++) 
+				reqbuf->XBuffer.P[l++] = hlc[i];
+		}
+	}
+        reqbuf->XBuffer.P[l++] = CAI;
+        reqbuf->XBuffer.P[l++] = 6;
+        reqbuf->XBuffer.P[l++] = 0x09;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 32;
+	reqbuf->XBuffer.P[l++] = 3;
+        switch(chan->l2prot) {
+		case ISDN_PROTO_L2_X75I:
+		case ISDN_PROTO_L2_X75UI:
+		case ISDN_PROTO_L2_X75BUI:
+                case ISDN_PROTO_L2_HDLC:
+                        reqbuf->XBuffer.P[l-6] = 5;
+                        reqbuf->XBuffer.P[l-7] = 1;
+			l -= 5; 
+                        break;
+                case ISDN_PROTO_L2_V11096:
+                        reqbuf->XBuffer.P[l-7] = 3;
+                        reqbuf->XBuffer.P[l-6] = 0x0d;
+                        reqbuf->XBuffer.P[l-5] = 5;
+                        reqbuf->XBuffer.P[l-4] = 0;
+                        l -= 3;
+                        break;
+                case ISDN_PROTO_L2_V11019:
+                        reqbuf->XBuffer.P[l-7] = 3;
+                        reqbuf->XBuffer.P[l-6] = 0x0d;
+                        reqbuf->XBuffer.P[l-5] = 6;
+                        reqbuf->XBuffer.P[l-4] = 0;
+                        l -= 3;
+                        break;
+                case ISDN_PROTO_L2_V11038:
+                        reqbuf->XBuffer.P[l-7] = 3;
+                        reqbuf->XBuffer.P[l-6] = 0x0d;
+                        reqbuf->XBuffer.P[l-5] = 7;
+                        reqbuf->XBuffer.P[l-4] = 0;
+                        l -= 3;
+                        break;
+                case ISDN_PROTO_L2_MODEM:
+			reqbuf->XBuffer.P[l-6] = 0x11;
+			reqbuf->XBuffer.P[l-5] = 7;
+			reqbuf->XBuffer.P[l-4] = 0;
+			reqbuf->XBuffer.P[l-3] = 0;
+			reqbuf->XBuffer.P[l-2] = 128;
+			reqbuf->XBuffer.P[l-1] = 0;
+                        break;
+        }
+	
+	reqbuf->XBuffer.P[l++] = 0; /* end */
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 0; /* Sig Entity */
+
+	skb_queue_tail(&chan->e.X, skb);
+	skb_queue_tail(&card->sndq, skb2); 
+	eicon_schedule_tx(card);
+
+	if (DebugVar & 8)
+  		printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone);
+   return(0);
+}
+
+
+void
+idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len)
+{
+	int i,j;
+	int pos = 0;
+	int codeset = 0;
+	int wlen = 0;
+	int lock = 0;
+	__u8 w;
+	__u16 code;
+	isdn_ctrl cmd;
+
+  memset(message, 0, sizeof(idi_ind_message));
+
+  if ((!len) || (!buffer[pos])) return;
+  while(pos <= len) {
+	w = buffer[pos++];
+	if (!w) return;
+	if (w & 0x80) {
+		wlen = 0;
+	}
+	else {
+		wlen = buffer[pos++];
+	}
+
+	if (pos > len) return;
+
+	if (lock & 0x80) lock &= 0x7f;
+	else codeset = lock;
+
+	if((w&0xf0) == SHIFT) {
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 13'
echo 'File patch-2.3.4 is continued in part 14'
echo 14 > _shar_seq_.tmp
#!/bin/sh
# this is part 16 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 16; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+		if (argc) {
+			membase = ints[i];
+			i++;
+			argc--;
+		}
+		if (argc) {
+			irq = ints[i];
+			i++;
+			argc--;
+		}
+		if (strlen(str)) {
+			strcpy(id, str);
+		} else {
+			strcpy(id, "eicon");
+		} 
+		/* eicon_addcard(0, membase, irq, id); */
+       		printk(KERN_INFO "eicon: membase=0x%x irq=%d id=%s\n", membase, irq, id);
+	}
+}
+#endif
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/eicon/eicon_pci.c linux/drivers/isdn/eicon/eicon_pci.c
--- v2.3.3/linux/drivers/isdn/eicon/eicon_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/eicon/eicon_pci.c	Wed May 26 16:55:40 1999
@@ -0,0 +1,952 @@
+/* $Id: eicon_pci.c,v 1.6 1999/04/01 12:48:37 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * Hardware-specific code for PCI cards.
+ *
+ * Copyright 1998,99 by Armin Schindler (m...@melware.de)
+ * Copyright 1999    Cytronics & Melware (in...@melware.de)
+ *
+ * Thanks to	Eicon Technology Diehl GmbH & Co. oHG for 
+ *		documents, informations and hardware. 
+ *
+ *		Deutsche Telekom AG for S2M support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_pci.c,v $
+ * Revision 1.6  1999/04/01 12:48:37  armin
+ * Changed some log outputs.
+ *
+ * Revision 1.5  1999/03/29 11:19:49  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.4 1999/03/02 12:37:48 armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.3 1999/01/24 20:14:24 armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.2 1999/01/10 18:46:06 armin
+ * Bug with wrong values in HLC fixed.
+ * Bytes to send are counted and limited now.
+ *
+ * Revision 1.1 1999/01/01 18:09:45 armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/pci.h>
+
+#include "eicon.h"
+#include "eicon_pci.h"
+
+
+char *eicon_pci_revision = "$Revision: 1.6 $";
+
+#if CONFIG_PCI	         /* intire stuff is only for PCI */
+
+#undef EICON_PCI_DEBUG 
+
+int eicon_pci_find_card(char *ID)
+{
+  if (pci_present()) { 
+    struct pci_dev *pdev = NULL;  
+    int pci_nextindex=0, pci_cards=0, pci_akt=0; 
+    int pci_type = PCI_MAESTRA;
+    int NoMorePCICards = FALSE;
+    char *ram, *reg, *cfg;	
+    unsigned int pram=0, preg=0, pcfg=0;
+    char did[12];
+    eicon_pci_card *aparms;
+
+   if (!(aparms = (eicon_pci_card *) kmalloc(sizeof(eicon_pci_card), GFP_KERNEL))) {
+                  printk(KERN_WARNING
+                      "eicon_pci: Could not allocate card-struct.\n");
+                  return 0;
+   }
+
+  for (pci_cards = 0; pci_cards < 0x0f; pci_cards++)
+  {
+  do {
+      if ((pdev = pci_find_device(PCI_VENDOR_EICON,          
+                                  pci_type,                  
+                                  pdev)))                    
+	{
+              pci_nextindex++;
+              break;
+	}
+	else {
+              pci_nextindex = 0;
+              switch (pci_type) /* switch to next card type */
+               {
+               case PCI_MAESTRA:
+                 pci_type = PCI_MAESTRAQ; break;
+               case PCI_MAESTRAQ:
+                 pci_type = PCI_MAESTRAQ_U; break;
+               case PCI_MAESTRAQ_U:
+                 pci_type = PCI_MAESTRAP; break;
+               default:
+               case PCI_MAESTRAP:
+                 NoMorePCICards = TRUE;
+               }
+	}
+     }
+     while (!NoMorePCICards);
+     if (NoMorePCICards)
+        {
+           if (pci_cards < 1) {
+           printk(KERN_INFO "Eicon: No supported PCI cards found.\n");
+	   kfree(aparms);	
+           return 0;
+           }
+           else
+           {
+           printk(KERN_INFO "Eicon: %d PCI card%s registered.\n",
+			pci_cards, (pci_cards > 1) ? "s":"");
+	   kfree(aparms);	
+           return (pci_cards);
+           }
+        }
+
+   pci_akt = 0;
+   switch(pci_type)
+   {
+    case PCI_MAESTRA:
+         printk(KERN_INFO "Eicon: DIVA Server BRI/PCI detected !\n");
+          aparms->type = EICON_CTYPE_MAESTRA;
+
+          aparms->irq = pdev->irq;
+          preg = pdev->base_address[2] & 0xfffffffc;
+          pcfg = pdev->base_address[1] & 0xffffff80;
+
+#ifdef EICON_PCI_DEBUG
+          printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
+          printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", preg);
+          printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", pcfg);
+#endif
+	 pci_akt = 1;
+         break;
+
+    case PCI_MAESTRAQ:
+    case PCI_MAESTRAQ_U:
+         printk(KERN_ERR "Eicon: DIVA Server 4BRI/PCI detected but not supported !\n");
+         pci_cards--;
+	 pci_akt = 0;
+         break;
+
+    case PCI_MAESTRAP:
+         printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n");
+          aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/
+          aparms->irq = pdev->irq;
+          pram = pdev->base_address[0] & 0xfffff000;
+          preg = pdev->base_address[2] & 0xfffff000;
+          pcfg = pdev->base_address[4] & 0xfffff000;
+
+#ifdef EICON_PCI_DEBUG
+          printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
+          printk(KERN_DEBUG "eicon_pci: ram=0x%x\n",
+               (pram));
+          printk(KERN_DEBUG "eicon_pci: reg=0x%x\n",
+               (preg));
+          printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n",
+               (pcfg));
+#endif
+	  pci_akt = 1;
+	  break;	
+    default:
+         printk(KERN_ERR "eicon_pci: Unknown PCI card detected !\n");
+         pci_cards--;
+	 pci_akt = 0;
+	 break;
+   }
+
+	if (pci_akt) {
+		/* remapping memory */
+		switch(pci_type)
+		{
+    		case PCI_MAESTRA:
+			aparms->PCIreg = (unsigned int) preg;
+			aparms->PCIcfg = (unsigned int) pcfg;
+			if (check_region((aparms->PCIreg), 0x20)) {
+				printk(KERN_WARNING "eicon_pci: reg port already in use !\n");
+				aparms->PCIreg = 0;
+				break;	
+			} else {
+				request_region(aparms->PCIreg, 0x20, "eicon reg");
+			}
+			if (check_region((aparms->PCIcfg), 0x100)) {
+				printk(KERN_WARNING "eicon_pci: cfg port already in use !\n");
+				aparms->PCIcfg = 0;
+				break;	
+			} else {
+				request_region(aparms->PCIcfg, 0x100, "eicon cfg");
+			}
+			break;
+    		case PCI_MAESTRAQ:
+		case PCI_MAESTRAQ_U:
+		case PCI_MAESTRAP:
+			aparms->shmem = (eicon_pci_shmem *) ioremap(pram, 0x10000);
+			ram = (u8 *) ((u32)aparms->shmem + MP_SHARED_RAM_OFFSET);
+			reg =  ioremap(preg, 0x4000);
+			cfg =  ioremap(pcfg, 0x1000);	
+			aparms->PCIram = (unsigned int) ram;
+			aparms->PCIreg = (unsigned int) reg;
+			aparms->PCIcfg = (unsigned int) cfg;
+			break;
+		 }
+		if ((!aparms->PCIreg) || (!aparms->PCIcfg)) {
+			printk(KERN_ERR "eicon_pci: Card could not be added !\n");
+			pci_cards--;
+		} else {
+			aparms->mvalid = 1;
+	
+			sprintf(did, "%s%d", (strlen(ID) < 1) ? "eicon":ID, pci_cards);
+
+			printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[aparms->type] , did);
+
+			if (!(eicon_addcard(aparms->type, (int) aparms, aparms->irq, did))) {
+				printk(KERN_ERR "eicon_pci: Card could not be added !\n");
+				pci_cards--;
+			}
+		}
+	}
+
+  }
+ } else
+	printk(KERN_ERR "eicon_pci: Kernel compiled with PCI but no PCI-bios found !\n");
+ return 0;
+}
+
+/*
+ * Checks protocol file id for "F#xxxx" string fragment to
+ * extract the features, supported by this protocol version.
+ * binary representation of the feature string value is returned
+ * in *value. The function returns 0 if feature string was not
+ * found or has a wrong format, else 1.
+ */
+static int GetProtFeatureValue(char *sw_id, int *value)
+{
+  __u8 i, offset;
+
+  while (*sw_id)
+  {
+    if ((sw_id[0] == 'F') && (sw_id[1] == '#'))
+    {
+      sw_id = &sw_id[2];
+      for (i=0, *value=0; i<4; i++, sw_id++)
+      {
+        if ((*sw_id >= '0') && (*sw_id <= '9'))
+        {
+          offset = '0';
+        }
+        else if ((*sw_id >= 'A') && (*sw_id <= 'F'))
+        {
+          offset = 'A' + 10;
+        }
+        else if ((*sw_id >= 'a') && (*sw_id <= 'f'))
+        {
+          offset = 'a' + 10;
+        }
+        else
+        {
+          return 0;
+        }
+        *value |= (*sw_id - offset) << (4*(3-i));
+      }
+      return 1;
+    }
+    else
+    {
+      sw_id++;
+    }
+  }
+  return 0;
+}
+
+
+void
+eicon_pci_printpar(eicon_pci_card *card) {
+        switch (card->type) {
+                case EICON_CTYPE_MAESTRA:
+			printk(KERN_INFO "%s at 0x%x / 0x%x, irq %d\n",
+				eicon_ctype_name[card->type],
+				(unsigned int)card->PCIreg,
+				(unsigned int)card->PCIcfg,
+				card->irq); 
+			break;
+                case EICON_CTYPE_MAESTRAQ:
+                case EICON_CTYPE_MAESTRAQ_U:
+                case EICON_CTYPE_MAESTRAP:
+			printk(KERN_INFO "%s at 0x%x, irq %d\n",
+				eicon_ctype_name[card->type],
+				(unsigned int)card->shmem,
+				card->irq); 
+#ifdef EICON_PCI_DEBUG
+		        printk(KERN_INFO "eicon_pci: remapped ram= 0x%x\n",(unsigned int)card->PCIram);
+		        printk(KERN_INFO "eicon_pci: remapped reg= 0x%x\n",(unsigned int)card->PCIreg);
+		        printk(KERN_INFO "eicon_pci: remapped cfg= 0x%x\n",(unsigned int)card->PCIcfg); 
+#endif
+			break;
+	}
+}
+
+
+static void
+eicon_pci_release_shmem(eicon_pci_card *card) {
+	if (!card->master)
+		return;
+	if (card->mvalid) {
+        	switch (card->type) {
+                	case EICON_CTYPE_MAESTRA:
+			        /* reset board */
+				outb(0, card->PCIcfg + 0x4c);	/* disable interrupts from PLX */
+				outb(0, card->PCIreg + M_RESET);
+				SLEEP(20);
+				outb(0, card->PCIreg + M_ADDRH);
+				outw(0, card->PCIreg + M_ADDR);
+				outw(0, card->PCIreg + M_DATA);
+
+				release_region(card->PCIreg, 0x20);
+				release_region(card->PCIcfg, 0x100);
+				break;
+                	case EICON_CTYPE_MAESTRAQ:
+	                case EICON_CTYPE_MAESTRAQ_U:
+	                case EICON_CTYPE_MAESTRAP:
+			        /* reset board */
+		        	writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
+			        SLEEP(20);
+			        writeb(0, card->PCIreg + MP_RESET);
+			        SLEEP(20);
+
+				iounmap((void *)card->shmem);
+				iounmap((void *)card->PCIreg);
+				iounmap((void *)card->PCIcfg);
+				break;
+		}
+	}
+	card->mvalid = 0;
+}
+
+static void
+eicon_pci_release_irq(eicon_pci_card *card) {
+	if (!card->master)
+		return;
+	if (card->ivalid)
+		free_irq(card->irq, card);
+	card->ivalid = 0;
+}
+
+void
+eicon_pci_release(eicon_pci_card *card) {
+        eicon_pci_release_irq(card);
+        eicon_pci_release_shmem(card);
+}
+
+/*
+ * Upload buffer content to adapters shared memory
+ * on verify error, 1 is returned and a message is printed on screen
+ * else 0 is returned
+ * Can serve IO-Type and Memory type adapters
+ */
+int eicon_upload(t_dsp_download_space   *p_para,
+            __u16                 length,   /* byte count */
+            __u8                  *buffer,
+            int                   verify)
+{
+  __u32               i, dwdata = 0, val = 0, timeout;
+  __u16               data;
+  eicon_pci_boot *boot = 0;
+
+  switch (p_para->type) /* actions depend on type of union */
+  {
+    case DL_PARA_IO_TYPE:
+      for (i=0; i<length; i+=2)
+      {
+	outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
+	outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); 
+	/* outw (((u16 *)code)[i >> 1], p_para->dat.io.ioDATA); */
+	outw (*(u16 *)&buffer[i], p_para->dat.io.ioDATA); 
+      }
+      if (verify) /* check written block */
+      {
+        for (i=0; i<length; i+=2)
+        {
+	  outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
+          outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); 
+          data = inw(p_para->dat.io.ioDATA);
+          if (data != *(u16 *)&buffer[i])
+          {
+            p_para->dat.io.r3addr  += i;
+            p_para->dat.io.BadData  = data;
+            p_para->dat.io.GoodData = *(u16 *)&buffer[i];
+            return 1;
+          }
+        }
+      }
+      break;
+
+    case DL_PARA_MEM_TYPE:
+      boot = p_para->dat.mem.boot;
+      writel(p_para->dat.mem.r3addr, &boot->addr);
+      for (i=0; i<length; i+=4)
+      {
+        writel(((u32 *)buffer)[i >> 2], &boot->data[i]);
+      }
+      if (verify) /* check written block */
+      {
+        for (i=0; i<length; i+=4)
+        {
+          dwdata = readl(&boot->data[i]);
+          if (((u32 *)buffer)[i >> 2] != dwdata)
+          {
+            p_para->dat.mem.r3addr  += i;
+            p_para->dat.mem.BadData  = dwdata;
+            p_para->dat.mem.GoodData = ((u32 *)buffer)[i >> 2];
+            return 1;
+          }
+        }
+      }
+      writel(((length + 3) / 4), &boot->len);  /* len in dwords */
+      writel(2, &boot->cmd);
+
+	timeout = jiffies + 20;
+	while (timeout > jiffies) {
+		val = readl(&boot->cmd);
+		if (!val) break;
+		SLEEP(2);
+	}
+	if (val)
+         {
+		p_para->dat.mem.timeout = 1;
+		return 1;
+	 }
+      break;
+  }
+  return 0;
+}
+
+
+/* show header information of code file */
+static
+int eicon_pci_print_hdr(unsigned char *code, int offset)
+{
+  unsigned char hdr[80];
+  int i, fvalue = 0;
+
+  i = 0;
+  while ((i < (sizeof(hdr) -1))
+          && (code[offset + i] != '\0')
+          && (code[offset + i] != '\r')
+          && (code[offset + i] != '\n'))
+   {
+     hdr[i] = code[offset + i];
+     i++;
+   }
+   hdr[i] = '\0';
+   printk(KERN_DEBUG "Eicon: loading %s\n", hdr);
+   if (GetProtFeatureValue(hdr, &fvalue)) return(fvalue);
+    else return(0);
+}
+
+
+/*
+ * Configure a card, download code into BRI card,
+ * check if we get interrupts and return 0 on succes.
+ * Return -ERRNO on failure.
+ */
+int
+eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
+        int               i,j;
+        int               timeout;
+	unsigned int	  offset, offp=0, size, length;
+	int		  signature = 0;
+	int		  FeatureValue = 0;
+        eicon_pci_codebuf cbuf;
+	t_dsp_download_space dl_para;
+	t_dsp_download_desc  dsp_download_table;
+        unsigned char     *code;
+	unsigned int	  reg;
+	unsigned int	  cfg;
+
+        if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
+                return -EFAULT;
+
+	reg = card->PCIreg;
+	cfg = card->PCIcfg;
+
+	/* reset board */
+	outb(0, reg + M_RESET);
+	SLEEP(10);
+	outb(0, reg + M_ADDRH);
+	outw(0, reg + M_ADDR);
+	outw(0, reg + M_DATA);
+
+#ifdef EICON_PCI_DEBUG
+	 printk(KERN_DEBUG "eicon_pci: reset card\n");
+#endif
+
+	/* clear shared memory */
+	outb(0xff, reg + M_ADDRH);
+	outw(0, reg + M_ADDR);
+	for(i = 0; i < 0xffff; i++) outw(0, reg + M_DATA);
+	SLEEP(10);
+
+#ifdef EICON_PCI_DEBUG
+	 printk(KERN_DEBUG "eicon_pci: clear shared memory\n");
+#endif
+
+	/* download protocol and dsp file */
+
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
+#endif
+
+       	/* Allocate code-buffer */
+       	if (!(code = kmalloc(400, GFP_KERNEL))) {
+                printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
+       	        return -ENOMEM;
+        }
+
+	/* prepare protocol upload */
+	dl_para.type		= DL_PARA_IO_TYPE;
+	dl_para.dat.io.ioADDR	= reg + M_ADDR;
+	dl_para.dat.io.ioADDRH	= reg + M_ADDRH;
+	dl_para.dat.io.ioDATA	= reg + M_DATA;
+
+	for (j = 0; j <= cbuf.dsp_code_num; j++) 
+	 {	
+	   if (j == 0)  size = cbuf.protocol_len;
+	           else size = cbuf.dsp_code_len[j];
+
+        	offset = 0;
+
+		if (j == 0) dl_para.dat.io.r3addr = 0;
+		if (j == 1) dl_para.dat.io.r3addr = M_DSP_CODE_BASE +
+					((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
+		if (j == 2) dl_para.dat.io.r3addr = M_DSP_CODE_BASE;
+		if (j == 3) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + sizeof(__u32);
+
+           do  /* download block of up to 400 bytes */
+            {
+              length = ((size - offset) >= 400) ? 400 : (size - offset);
+
+        	if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
+                	kfree(code);
+	                return -EFAULT;
+        	}
+
+		if ((offset == 0) && (j < 2)) {
+		       	FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); 
+#ifdef EICON_PCI_DEBUG
+	if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%04x.\n", FeatureValue);
+#endif
+			if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
+                  		printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
+				kfree(code);
+		                return -EFAULT;
+			}
+                	((eicon_card *)card->card)->Feature = FeatureValue;
+		}
+
+		if (eicon_upload(&dl_para, length, code, 1))
+		{
+                  printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
+		  kfree(code);
+                  return -EIO;
+		}
+              /* move onto next block */
+              offset += length;
+	      dl_para.dat.io.r3addr += length;
+            } while (offset < size);
+
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "Eicon: %d bytes loaded.\n", offset);
+#endif
+	offp += size;
+	}
+	kfree(code);	
+
+	/* clear signature */
+	outb(0xff, reg + M_ADDRH);
+	outw(0x1e, reg + M_ADDR);
+	outw(0, reg + M_DATA);
+
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
+#endif
+	/* copy configuration data into shared memory */
+	outw(8, reg + M_ADDR); outb(cbuf.tei, reg + M_DATA);
+	outw(9, reg + M_ADDR); outb(cbuf.nt2, reg + M_DATA);
+	outw(10,reg + M_ADDR); outb(0, reg + M_DATA);
+	outw(11,reg + M_ADDR); outb(cbuf.WatchDog, reg + M_DATA);
+	outw(12,reg + M_ADDR); outb(cbuf.Permanent, reg + M_DATA);
+	outw(13,reg + M_ADDR); outb(0, reg + M_DATA);                 /* XInterface */
+	outw(14,reg + M_ADDR); outb(cbuf.StableL2, reg + M_DATA);
+	outw(15,reg + M_ADDR); outb(cbuf.NoOrderCheck, reg + M_DATA);
+	outw(16,reg + M_ADDR); outb(0, reg + M_DATA);                 /* HandsetType */
+	outw(17,reg + M_ADDR); outb(0, reg + M_DATA);                 /* SigFlags */
+	outw(18,reg + M_ADDR); outb(cbuf.LowChannel, reg + M_DATA);
+	outw(19,reg + M_ADDR); outb(cbuf.ProtVersion, reg + M_DATA);
+	outw(20,reg + M_ADDR); outb(cbuf.Crc4, reg + M_DATA);
+	outw(21,reg + M_ADDR); outb((cbuf.Loopback) ? 2:0, reg + M_DATA);
+
+	for (i=0;i<32;i++)
+	{
+		outw( 32+i, reg + M_ADDR); outb(cbuf.l[0].oad[i], reg + M_DATA);
+		outw( 64+i, reg + M_ADDR); outb(cbuf.l[0].osa[i], reg + M_DATA);
+		outw( 96+i, reg + M_ADDR); outb(cbuf.l[0].spid[i], reg + M_DATA);
+		outw(128+i, reg + M_ADDR); outb(cbuf.l[1].oad[i], reg + M_DATA);
+		outw(160+i, reg + M_ADDR); outb(cbuf.l[1].osa[i], reg + M_DATA);
+		outw(192+i, reg + M_ADDR); outb(cbuf.l[1].spid[i], reg + M_DATA);
+	}
+
+#ifdef EICON_PCI_DEBUG
+           printk(KERN_ERR "eicon_pci: starting CPU...\n");
+#endif
+	/* let the CPU run */
+	outw(0x08, reg + M_RESET);
+
+        timeout = jiffies + (5*HZ);
+        while (timeout > jiffies) {
+	   outw(0x1e, reg + M_ADDR);	
+           signature = inw(reg + M_DATA);
+           if (signature == DIVAS_SIGNATURE) break;
+           SLEEP(2);
+         }
+        if (signature != DIVAS_SIGNATURE)
+         {
+#ifdef EICON_PCI_DEBUG
+           printk(KERN_ERR "eicon_pci: signature 0x%x expected 0x%x\n",signature,DIVAS_SIGNATURE);
+#endif
+           printk(KERN_ERR "eicon_pci: Timeout, protocol code not running !\n");
+           return -EIO; 
+         }
+#ifdef EICON_PCI_DEBUG
+        printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
+#endif
+
+        /* get serial number and number of channels supported by card */
+	outb(0xff, reg + M_ADDRH);
+	outw(0x3f6, reg + M_ADDR);
+        card->channels = inw(reg + M_DATA);
+        card->serial = (u32)inw(cfg + 0x22) << 16 | (u32)inw(cfg + 0x26);
+        printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
+        printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
+
+        /* test interrupt */
+        card->irqprobe = 1;
+
+        if (!card->ivalid) {
+                if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card))
+                 {
+                  printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
+                  return -EIO;
+                 }
+        }
+        card->ivalid = 1;
+
+#ifdef EICON_PCI_DEBUG
+        printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
+#endif
+        /* Trigger an interrupt and check if it is delivered */
+        outb(0x41, cfg + 0x4c);		/* enable PLX for interrupts */
+	outb(0x89, reg + M_RESET);	/* place int request */
+
+        timeout = jiffies + 20;
+        while (timeout > jiffies) {
+          if (card->irqprobe != 1) break;
+          SLEEP(5);
+         }
+        if (card->irqprobe == 1) {
+           free_irq(card->irq, card); 
+           card->ivalid = 0; 
+           printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
+           return -EIO;
+         }
+
+   /* initializing some variables */
+   ((eicon_card *)card->card)->ReadyInt = 0;
+   for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
+   for(j=0; j< (card->channels + 1); j++) {
+                ((eicon_card *)card->card)->bch[j].e.busy = 0;
+                ((eicon_card *)card->card)->bch[j].e.D3Id = 0;
+                ((eicon_card *)card->card)->bch[j].e.B2Id = 0;
+                ((eicon_card *)card->card)->bch[j].e.ref = 0;
+                ((eicon_card *)card->card)->bch[j].e.Req = 0;
+                ((eicon_card *)card->card)->bch[j].e.complete = 1;
+                ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
+   }
+
+   printk(KERN_INFO "Eicon: Card successfully started\n");
+
+ return 0;
+}
+
+
+/*
+ * Configure a card, download code into PRI card,
+ * check if we get interrupts and return 0 on succes.
+ * Return -ERRNO on failure.
+ */
+int
+eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
+        eicon_pci_boot    *boot;
+	eicon_pr_ram  *prram;
+        int               i,j;
+        int               timeout;
+	int		  FeatureValue = 0;
+	unsigned int	  offset, offp=0, size, length;
+	unsigned long int signature = 0;
+	t_dsp_download_space dl_para;
+	t_dsp_download_desc  dsp_download_table;
+        eicon_pci_codebuf cbuf;
+        unsigned char     *code;
+	unsigned char	  req_int;
+    	char *ram, *reg, *cfg;	
+
+        if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
+                return -EFAULT;
+
+        boot = &card->shmem->boot;
+	ram = (char *)card->PCIram;
+	reg = (char *)card->PCIreg;
+	cfg = (char *)card->PCIcfg;
+	prram = (eicon_pr_ram *)ram;
+
+	/* reset board */
+	writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
+	SLEEP(20);
+	writeb(0, card->PCIreg + MP_RESET);
+	SLEEP(20);
+
+	/* set command count to 0 */
+	writel(0, &boot->reserved); 
+
+	/* check if CPU increments the life word */
+        i = readw(&boot->live);
+        SLEEP(20);
+        if (i == readw(&boot->live)) {
+           printk(KERN_ERR "eicon_pci: card is reset, but CPU not running !\n");
+           return -EIO;
+         }
+#ifdef EICON_PCI_DEBUG
+	 printk(KERN_DEBUG "eicon_pci: reset card OK (CPU running)\n");
+#endif
+
+	/* download firmware : DSP and Protocol */
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
+#endif
+
+       	/* Allocate code-buffer */
+       	if (!(code = kmalloc(400, GFP_KERNEL))) {
+                printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
+       	        return -ENOMEM;
+        }
+
+	/* prepare protocol upload */
+	dl_para.type		= DL_PARA_MEM_TYPE;
+	dl_para.dat.mem.boot	= boot;
+
+        for (j = 0; j <= cbuf.dsp_code_num; j++)
+         {
+	   if (j==0) size = cbuf.protocol_len;
+		else size = cbuf.dsp_code_len[j];	
+
+           if (j==1) writel(MP_DSP_ADDR, &boot->addr); /* DSP code entry point */
+
+		if (j == 0) dl_para.dat.io.r3addr = MP_PROTOCOL_ADDR;
+		if (j == 1) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE +
+					((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
+		if (j == 2) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE;
+		if (j == 3) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + sizeof(__u32);
+
+           offset = 0;
+           do  /* download block of up to 400 bytes */
+            {
+              length = ((size - offset) >= 400) ? 400 : (size - offset);
+
+        	if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
+                	kfree(code);
+	                return -EFAULT;
+        	}
+
+		if ((offset == 0) && (j < 2)) {
+	           	FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); 
+#ifdef EICON_PCI_DEBUG
+	if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%x.\n", FeatureValue);
+#endif
+			if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
+                  		printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
+				kfree(code);
+		                return -EFAULT;
+			}
+                	((eicon_card *)card->card)->Feature = FeatureValue;
+		}
+
+		if (eicon_upload(&dl_para, length, code, 1))
+		{
+		  if (dl_para.dat.mem.timeout == 0)
+	                  printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
+			else
+			  printk(KERN_ERR "eicon_pci: timeout, no ACK to load !\n");
+		  kfree(code);
+                  return -EIO;
+		}
+
+              /* move onto next block */
+              offset += length;
+	      dl_para.dat.mem.r3addr += length;
+            } while (offset < size);
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: %d bytes loaded.\n", offset);
+#endif
+	 offp += size;
+         }
+	 kfree(code);	
+
+	/* initialize the adapter data structure */
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
+#endif
+        /* clear out config space */
+        for (i = 0; i < 256; i++) writeb(0, &ram[i]);
+
+        /* copy configuration down to the card */
+        writeb(cbuf.tei, &ram[8]);
+        writeb(cbuf.nt2, &ram[9]);
+        writeb(0, &ram[10]);
+        writeb(cbuf.WatchDog, &ram[11]);
+        writeb(cbuf.Permanent, &ram[12]);
+        writeb(cbuf.XInterface, &ram[13]);
+        writeb(cbuf.StableL2, &ram[14]);
+        writeb(cbuf.NoOrderCheck, &ram[15]);
+        writeb(cbuf.HandsetType, &ram[16]);
+        writeb(0, &ram[17]);
+        writeb(cbuf.LowChannel, &ram[18]);
+        writeb(cbuf.ProtVersion, &ram[19]);
+        writeb(cbuf.Crc4, &ram[20]);
+        for (i = 0; i < 32; i++)
+         {
+           writeb(cbuf.l[0].oad[i], &ram[32 + i]);
+           writeb(cbuf.l[0].osa[i], &ram[64 + i]);
+           writeb(cbuf.l[0].spid[i], &ram[96 + i]);
+           writeb(cbuf.l[1].oad[i], &ram[128 + i]);
+           writeb(cbuf.l[1].osa[i], &ram[160 + i]);
+           writeb(cbuf.l[1].spid[i], &ram[192 + i]);
+         }
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: configured card OK\n");
+#endif
+
+	/* start adapter */
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: tell card to start...\n");
+#endif
+        writel(MP_PROTOCOL_ADDR, &boot->addr); /* RISC code entry point */
+        writel(3, &boot->cmd); /* DIVAS_START_CMD */
+
+        /* wait till card ACKs */
+        timeout = jiffies + (5*HZ);
+        while (timeout > jiffies) {
+           signature = readl(&boot->signature);
+           if ((signature >> 16) == DIVAS_SIGNATURE) break;
+           SLEEP(2);
+         }
+        if ((signature >> 16) != DIVAS_SIGNATURE)
+         {
+#ifdef EICON_PCI_DEBUG
+           printk(KERN_ERR "eicon_pci: signature 0x%lx expected 0x%x\n",(signature >> 16),DIVAS_SIGNATURE);
+#endif
+           printk(KERN_ERR "eicon_pci: timeout, protocol code not running !\n");
+           return -EIO;
+         }
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
+#endif
+
+	/* get serial number and number of channels supported by card */
+        card->channels = readb(&ram[0x3f6]);
+        card->serial = readl(&ram[0x3f0]);
+        printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
+        printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
+
+	/* test interrupt */
+	readb(&ram[0x3fe]);
+        writeb(0, &ram[0x3fe]); /* reset any pending interrupt */
+	readb(&ram[0x3fe]);
+
+        writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
+        writew(0, &cfg[MP_IRQ_RESET + 2]);
+
+        card->irqprobe = 1;
+
+	if (!card->ivalid) {
+	        if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) 
+        	 {
+	          printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
+        	  return -EIO;
+	         }
+	}
+	card->ivalid = 1;
+
+        req_int = readb(&prram->ReadyInt);
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
+#endif
+        req_int++;
+        /* Trigger an interrupt and check if it is delivered */
+        writeb(req_int, &prram->ReadyInt);
+
+        timeout = jiffies + 20;
+        while (timeout > jiffies) {
+          if (card->irqprobe != 1) break;
+          SLEEP(2);
+         }
+        if (card->irqprobe == 1) {
+           free_irq(card->irq, card);
+	   card->ivalid = 0;
+           printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
+           return -EIO;
+         }
+
+   /* initializing some variables */
+   ((eicon_card *)card->card)->ReadyInt = 0;
+   for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
+   for(j=0; j< (card->channels + 1); j++) {
+		((eicon_card *)card->card)->bch[j].e.busy = 0;
+		((eicon_card *)card->card)->bch[j].e.D3Id = 0;
+		((eicon_card *)card->card)->bch[j].e.B2Id = 0;
+		((eicon_card *)card->card)->bch[j].e.ref = 0;
+		((eicon_card *)card->card)->bch[j].e.Req = 0;
+                ((eicon_card *)card->card)->bch[j].e.complete = 1;
+                ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
+   }
+
+   printk(KERN_INFO "Eicon: Card successfully started\n");
+
+ return 0;
+}
+
+#endif	/* CONFIG_PCI */
+
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/eicon/eicon_pci.h linux/drivers/isdn/eicon/eicon_pci.h
--- v2.3.3/linux/drivers/isdn/eicon/eicon_pci.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/eicon/eicon_pci.h	Sun May 23 10:03:41 1999
@@ -0,0 +1,188 @@
+/* $Id: eicon_pci.h,v 1.3 1999/03/29 11:19:51 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards (PCI part).
+ *
+ * Copyright 1998,99 by Armin Schindler (m...@melware.de)
+ * Copyright 1999    Cytronics & Melware (in...@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_pci.h,v $
+ * Revision 1.3  1999/03/29 11:19:51  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.2 1999/03/02 12:37:50 armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.1 1999/01/01 18:09:46 armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#ifndef eicon_pci_h
+#define eicon_pci_h
+
+#ifdef __KERNEL__
+
+
+#define PCI_VENDOR_EICON        0x1133
+#define PCI_DIVA_PRO20          0xe001	/* Not supported */
+#define PCI_DIVA20              0xe002	/* Not supported */
+#define PCI_DIVA_PRO20_U        0xe003	/* Not supported */
+#define PCI_DIVA20_U            0xe004	/* Not supported */
+#define PCI_MAESTRA             0xe010
+#define PCI_MAESTRAQ            0xe012
+#define PCI_MAESTRAQ_U          0xe013
+#define PCI_MAESTRAP            0xe014
+
+#define DIVA_PRO20          1
+#define DIVA20              2
+#define DIVA_PRO20_U        3
+#define DIVA20_U            4
+#define MAESTRA             5
+#define MAESTRAQ            6
+#define MAESTRAQ_U          7
+#define MAESTRAP            8
+
+#define TRUE  1
+#define FALSE 0
+
+#define DIVAS_SIGNATURE 0x4447
+
+
+/* MAESTRA BRI PCI */
+
+#define M_RESET		0x10		/* offset of reset register */
+#define M_DATA		0x00		/* offset of data register */
+#define M_ADDR		0x04		/* offset of address register */
+#define M_ADDRH		0x0c		/* offset of high address register */
+
+#define M_DSP_CODE_LEN            0xbf7d0000
+#define M_DSP_CODE                0xbf7d0004  /* max 128K DSP-Code */ 
+#define M_DSP_CODE_BASE           0xbf7a0000  
+#define M_MAX_DSP_CODE_SIZE       0x00050000  /* max 320K DSP-Code (Telindus) */
+
+
+
+/* MAESTRA PRI PCI */
+
+#define MP_SHARED_RAM_OFFSET 0x1000  /* offset of shared RAM base in the DRAM memory bar */
+
+#define MP_IRQ_RESET     0xc18       /* offset of interrupt status register in the CONFIG memory bar */
+#define MP_IRQ_RESET_VAL 0xfe        /* value to clear an interrupt */
+
+#define MP_PROTOCOL_ADDR 0xa0011000  /* load address of protocol code */
+#define MP_DSP_ADDR      0xa03c0000  /* load address of DSP code */
+#define MP_MAX_PROTOCOL_CODE_SIZE  0x000a0000   /* max 640K Protocol-Code */
+#define MP_DSP_CODE_BASE           0xa03a0000
+#define MP_MAX_DSP_CODE_SIZE       0x00060000   /* max 384K DSP-Code */
+
+#define MP_RESET         0x20        /* offset of RESET register in the DEVICES memory bar */
+
+/* RESET register bits */
+#define _MP_S2M_RESET    0x10        /* active lo   */
+#define _MP_LED2         0x08        /* 1 = on      */
+#define _MP_LED1         0x04        /* 1 = on      */
+#define _MP_DSP_RESET    0x02        /* active lo   */
+#define _MP_RISC_RESET   0x81        /* active hi, bit 7 for compatibility with old boards */
+
+/* boot interface structure */
+typedef struct {
+	__u32 cmd	__attribute__ ((packed));
+	__u32 addr	__attribute__ ((packed));
+	__u32 len	__attribute__ ((packed));
+	__u32 err	__attribute__ ((packed));
+	__u32 live	__attribute__ ((packed));
+	__u32 reserved[(0x1020>>2)-6] __attribute__ ((packed));
+	__u32 signature	__attribute__ ((packed));
+	__u8 data[1];    /* real interface description */
+} eicon_pci_boot;
+
+
+#define DL_PARA_IO_TYPE   0
+#define DL_PARA_MEM_TYPE  1
+
+typedef struct tag_dsp_download_space
+{
+  __u16 type;  /* see definitions above to differ union elements */
+  union
+  {
+    struct
+    {
+      __u32               r3addr;
+      __u16               ioADDR;
+      __u16               ioADDRH;
+      __u16               ioDATA;
+      __u16               BadData;  /* in case of verify error */
+      __u16               GoodData;
+    } io;     /* for io based adapters */
+    struct
+    {
+      __u32               r3addr;
+      eicon_pci_boot	  *boot;
+      __u32               BadData;  /* in case of verify error */
+      __u32               GoodData;
+      __u16               timeout;
+    } mem;    /* for memory based adapters */
+  } dat;
+} t_dsp_download_space;
+
+
+/* Shared memory */
+typedef union {
+	eicon_pci_boot boot;
+} eicon_pci_shmem;
+
+/*
+ * card's description
+ */
+typedef struct {
+	int		  ramsize;
+	int   		  irq;	    /* IRQ		          */
+	unsigned int      PCIram;
+	unsigned int	  PCIreg;
+	unsigned int	  PCIcfg;
+	long int   	  serial;   /* Serial No.		  */
+	int		  channels; /* No. of supported channels  */
+        void*             card;
+        eicon_pci_shmem*  shmem;    /* Shared-memory area         */
+        unsigned char*    intack;   /* Int-Acknowledge            */
+        unsigned char*    stopcpu;  /* Writing here stops CPU     */
+        unsigned char*    startcpu; /* Writing here starts CPU    */
+        unsigned char     type;     /* card type                  */
+        unsigned char     irqprobe; /* Flag: IRQ-probing          */
+        unsigned char     mvalid;   /* Flag: Memory is valid      */
+        unsigned char     ivalid;   /* Flag: IRQ is valid         */
+        unsigned char     master;   /* Flag: Card is Quadro 1/4   */
+        void*             generic;  /* Ptr to generic card struct */
+} eicon_pci_card;
+
+
+
+extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb);
+extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb);
+extern void eicon_pci_release(eicon_pci_card *card);
+extern void eicon_pci_printpar(eicon_pci_card *card);
+extern int eicon_pci_find_card(char *ID);
+
+#endif  /* __KERNEL__ */
+
+#endif	/* eicon_pci_h */
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile
--- v2.3.3/linux/drivers/isdn/hisax/Makefile	Mon Mar 15 16:11:29 1999
+++ linux/drivers/isdn/hisax/Makefile	Sun May 23 10:03:41 1999
@@ -8,7 +8,7 @@
X O_TARGET :=
X 
X O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \
-          lmgr.o q931.o callc.o fsm.o
+          lmgr.o q931.o callc.o fsm.o cert.o
X 
X # EXTRA_CFLAGS += -S
X 
@@ -27,6 +27,7 @@
X ISAC_OBJ :=
X ARCOFI_OBJ :=
X HSCX_OBJ :=
+ISAR_OBJ :=
X HFC_OBJ :=
X HFC_2BDS0 :=
X RAWHDLC_OBJ :=
@@ -43,12 +44,36 @@
X 	 HSCX_OBJ := hscx.o
X endif
X 
+ifeq ($(CONFIG_HISAX_TELESPCI),y)
+	 O_OBJS += telespci.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_S0BOX),y)
+	 O_OBJS += s0box.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
X ifeq ($(CONFIG_HISAX_AVM_A1),y)
X 	 O_OBJS += avm_a1.o
X 	 ISAC_OBJ := isac.o
X 	 HSCX_OBJ := hscx.o
X endif
X 
+ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y)
+	 O_OBJS += avm_a1p.o
+ 	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+ 
+ifeq ($(CONFIG_HISAX_FRITZPCI),y)
+	 O_OBJS += avm_pci.o
+ 	 ISAC_OBJ := isac.o
+endif
+
+
X ifeq ($(CONFIG_HISAX_ELSA),y)
X 	 O_OBJS += elsa.o
X 	 ISAC_OBJ := isac.o
@@ -84,6 +109,7 @@
X 	 O_OBJS += sedlbauer.o
X 	 ISAC_OBJ := isac.o
X 	 HSCX_OBJ := hscx.o
+	 ISAR_OBJ := isar.o
X endif
X 
X ifeq ($(CONFIG_HISAX_SPORTSTER),y)
@@ -101,6 +127,7 @@
X ifeq ($(CONFIG_HISAX_NETJET),y)
X 	 O_OBJS += netjet.o
X 	 ISAC_OBJ := isac.o
+#	 RAWHDLC_OBJ := rawhdlc.o
X endif
X 
X ifeq ($(CONFIG_HISAX_TELES3C),y)
@@ -108,10 +135,8 @@
X 	 HFC_2BDS0 := hfc_2bds0.o
X endif
X ifeq ($(CONFIG_HISAX_AMD7930),y)
-	 RAWHDLC_OBJ := foreign.o rawhdlc.o
-endif
-ifeq ($(CONFIG_HISAX_DBRI),y)
-	 RAWHDLC_OBJ := foreign.o rawhdlc.o
+	 O_OBJS += amd7930.o
+	 RAWHDLC_OBJ := rawhdlc.o
X endif
X 
X ifeq ($(CONFIG_HISAX_NICCY),y)
@@ -120,7 +145,8 @@
X 	 HSCX_OBJ := hscx.o
X endif
X 
-O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(HFC_OBJ) $(ARCOFI_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ)
+O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(ARCOFI_OBJ) 
+O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ) 
X OX_OBJS += config.o
X 
X O_TARGET :=
@@ -134,4 +160,14 @@
X   endif
X endif
X 
+
X include $(TOPDIR)/Rules.make
+
+MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
+	    tei.c callc.c cert.c l3dss1.c l3_1tr6.c elsa.c
+
+CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+
+cert.o:	$(MD5FILES) md5sums.asc
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c
+
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/arcofi.c linux/drivers/isdn/hisax/arcofi.c
--- v2.3.3/linux/drivers/isdn/hisax/arcofi.c	Thu Nov  5 09:58:43 1998
+++ linux/drivers/isdn/hisax/arcofi.c	Sun May 23 10:03:41 1999
@@ -1,12 +1,28 @@
-/* $Id: arcofi.c,v 1.1 1997/10/29 18:51:20 keil Exp $
+/* $Id: arcofi.c,v 1.6 1998/09/30 22:21:56 keil Exp $
X 
- * arcofi.h   Ansteuerung ARCOFI 2165
+ * arcofi.c   Ansteuerung ARCOFI 2165
X  *
X  * Author     Karsten Keil (ke...@temic-ech.spacenet.de)
X  *
X  *
X  *
X  * $Log: arcofi.c,v $
+ * Revision 1.6  1998/09/30 22:21:56  keil
+ * cosmetics
+ *
+ * Revision 1.5  1998/09/27 12:52:57  keil
+ * cosmetics
+ *
+ * Revision 1.4  1998/08/20 13:50:24  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.3  1998/05/25 12:57:38  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.2  1998/04/15 16:47:16  keil
+ * new interface
+ *
X  * Revision 1.1  1997/10/29 18:51:20  keil
X  * New files
X  *
@@ -18,18 +34,25 @@
X #include "isac.h"
X 
X int
-send_arcofi(struct IsdnCardState *cs, const u_char *msg) {
+send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
X 	u_char val;
-	char tmp[32];
X 	long flags;
-	int cnt=2;
+	int cnt=30;
X 	
X 	cs->mon_txp = 0;
X 	cs->mon_txc = msg[0];
X 	memcpy(cs->mon_tx, &msg[1], cs->mon_txc);
+	switch(bc) {
+		case 0: break;
+		case 1: cs->mon_tx[1] |= 0x40;
+			break;
+		default: break;
+	}
X 	cs->mocr &= 0x0f;
X 	cs->mocr |= 0xa0;
X 	test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags);
+	if (receive)
+		test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags);
X 	cs->writeisac(cs, ISAC_MOCR, cs->mocr);
X 	val = cs->readisac(cs, ISAC_MOSR);
X 	cs->writeisac(cs, ISAC_MOX1, cs->mon_tx[cs->mon_txp++]);
@@ -39,12 +62,18 @@
X 	sti();
X 	while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
X 		cnt--;
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+		udelay(500);
+	}
+	if (receive) {
+		while (cnt && !test_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
+			cnt--;
+			udelay(500);
+		}
X 	}
X 	restore_flags(flags);
-	sprintf(tmp, "arcofi tout %d", cnt);
-	debugl1(cs, tmp);
+	if (cnt <= 0) {
+		printk(KERN_WARNING"HiSax arcofi monitor timed out\n");
+		debugl1(cs, "HiSax arcofi monitor timed out");
+	}
X 	return(cnt);	
X }
-
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/arcofi.h linux/drivers/isdn/hisax/arcofi.h
--- v2.3.3/linux/drivers/isdn/hisax/arcofi.h	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/hisax/arcofi.h	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: arcofi.h,v 1.1 1997/10/29 18:51:20 keil Exp $
+/* $Id: arcofi.h,v 1.3 1998/05/25 12:57:39 keil Exp $
X 
X  * arcofi.h   Ansteuerung ARCOFI 2165
X  *
@@ -7,6 +7,13 @@
X  *
X  *
X  * $Log: arcofi.h,v $
+ * Revision 1.3  1998/05/25 12:57:39  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.2  1998/04/15 16:47:17  keil
+ * new interface
+ *
X  * Revision 1.1  1997/10/29 18:51:20  keil
X  * New files
X  *
@@ -14,4 +21,4 @@
X  
X #define ARCOFI_USE	1
X 
-extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg);
+extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/asuscom.c linux/drivers/isdn/hisax/asuscom.c
--- v2.3.3/linux/drivers/isdn/hisax/asuscom.c	Thu Nov  5 09:58:43 1998
+++ linux/drivers/isdn/hisax/asuscom.c	Sun May 23 10:03:41 1999
@@ -1,13 +1,22 @@
-/* $Id: asuscom.c,v 1.2 1998/02/02 13:27:06 keil Exp $
+/* $Id: asuscom.c,v 1.5 1998/11/15 23:54:19 keil Exp $
X 
X  * asuscom.c     low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
X  *
- * Author     Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author     Karsten Keil (ke...@isdn4linux.de)
X  *
X  * Thanks to  ASUSCOM NETWORK INC. Taiwan and  Dynalink NL for informations
X  *
X  *
X  * $Log: asuscom.c,v $
+ * Revision 1.5  1998/11/15 23:54:19  keil
+ * changes from 2.0
+ *
+ * Revision 1.4  1998/06/18 23:18:20  keil
+ * Support for new IPAC card
+ *
+ * Revision 1.3  1998/04/15 16:46:53  keil
+ * new init code
+ *
X  * Revision 1.2  1998/02/02 13:27:06  keil
X  * New
X  *
@@ -17,12 +26,13 @@
X #define __NO_VERSION__
X #include "hisax.h"
X #include "isac.h"
+#include "ipac.h"
X #include "hscx.h"
X #include "isdnl1.h"
X 
X extern const char *CardType[];
X 
-const char *Asuscom_revision = "$Revision: 1.2 $";
+const char *Asuscom_revision = "$Revision: 1.5 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -33,6 +43,12 @@
X #define ASUS_CTRL_U7	3
X #define ASUS_CTRL_POTS	5
X 
+#define ASUS_IPAC_ALE	0
+#define ASUS_IPAC_DATA	1
+
+#define ASUS_ISACHSCX	1
+#define ASUS_IPAC	2
+
X /* CARD_ADR (Write) */
X #define ASUS_RESET      0x80	/* Bit 7 Reset-Leitung */
X 
@@ -107,6 +123,30 @@
X }
X 
X static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
+}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
+}
+
+static u_char
X ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
X {
X 	return (readreg(cs->hw.asus.adr,
@@ -183,6 +223,52 @@
X 	}
X }
X 
+static void
+asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 20;
+
+	if (!cs) {
+		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "ASUS IRQ LOOP\n");
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0);
+}
+
X void
X release_io_asuscom(struct IsdnCardState *cs)
X {
@@ -197,14 +283,27 @@
X {
X 	long flags;
X 
-	byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
+	if (cs->subtyp == ASUS_IPAC)
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
+	else
+		byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
X 	save_flags(flags);
X 	sti();
X 	current->state = TASK_INTERRUPTIBLE;
X 	schedule_timeout(1);
-	byteout(cs->hw.asus.adr, 0);	/* Reset Off */
+	if (cs->subtyp == ASUS_IPAC)
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
+	else
+		byteout(cs->hw.asus.adr, 0);	/* Reset Off */
X 	current->state = TASK_INTERRUPTIBLE;
X 	schedule_timeout(1);
+	if (cs->subtyp == ASUS_IPAC) {
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12);
+	}
X 	restore_flags(flags);
X }
X 
@@ -219,13 +318,15 @@
X 			release_io_asuscom(cs);
X 			return(0);
X 		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &asuscom_interrupt,
+			if (cs->subtyp == ASUS_IPAC)
+				return(request_irq(cs->irq, &asuscom_interrupt_ipac,
+					I4L_IRQ_FLAG, "HiSax", cs));
+			else
+				return(request_irq(cs->irq, &asuscom_interrupt,
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			cs->debug |= L1_DEB_IPAC;
+			inithscxisac(cs, 3);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
@@ -238,6 +339,7 @@
X {
X 	int bytecnt;
X 	struct IsdnCardState *cs = card->cs;
+	u_char val;
X 	char tmp[64];
X 
X 	strcpy(tmp, Asuscom_revision);
@@ -248,12 +350,6 @@
X 	bytecnt = 8;
X 	cs->hw.asus.cfg_reg = card->para[1];
X 	cs->irq = card->para[0];
-	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
-	cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
-	cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
-	cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
-	cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-
X 	if (check_region((cs->hw.asus.cfg_reg), bytecnt)) {
X 		printk(KERN_WARNING
X 		       "HiSax: %s config port %x-%x already in use\n",
@@ -264,27 +360,45 @@
X 	} else {
X 		request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn");
X 	}
-
-	printk(KERN_INFO
-	       "ISDNLink: defined at 0x%x IRQ %d\n",
-	       cs->hw.asus.cfg_reg,
-	       cs->irq);
-	printk(KERN_INFO "ISDNLink: resetting card\n");
-	reset_asuscom(cs);
-	cs->readisac = &ReadISAC;
-	cs->writeisac = &WriteISAC;
-	cs->readisacfifo = &ReadISACfifo;
-	cs->writeisacfifo = &WriteISACfifo;
+	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
+		cs->hw.asus.cfg_reg, cs->irq);
X 	cs->BC_Read_Reg = &ReadHSCX;
X 	cs->BC_Write_Reg = &WriteHSCX;
X 	cs->BC_Send_Data = &hscx_fill_fifo;
X 	cs->cardmsg = &Asus_card_msg;
-	ISACVersion(cs, "ISDNLink:");
-	if (HscxVersion(cs, "ISDNLink:")) {
-		printk(KERN_WARNING
-		     "ISDNLink: wrong HSCX versions check IO address\n");
-		release_io_asuscom(cs);
-		return (0);
+	val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE, 
+		cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+	if (val == 1) {
+		cs->subtyp = ASUS_IPAC;
+		cs->hw.asus.adr  = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		cs->readisac = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		printk(KERN_INFO "Asus: IPAC version %x\n", val);
+	} else {
+		cs->subtyp = ASUS_ISACHSCX;
+		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		ISACVersion(cs, "ISDNLink:");
+		if (HscxVersion(cs, "ISDNLink:")) {
+			printk(KERN_WARNING
+		     	"ISDNLink: wrong HSCX versions check IO address\n");
+			release_io_asuscom(cs);
+			return (0);
+		}
X 	}
+	printk(KERN_INFO "ISDNLink: resetting card\n");
+	reset_asuscom(cs);
X 	return (1);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/avm_a1.c linux/drivers/isdn/hisax/avm_a1.c
--- v2.3.3/linux/drivers/isdn/hisax/avm_a1.c	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/avm_a1.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,20 @@
-/* $Id: avm_a1.c,v 2.7 1998/02/02 13:29:37 keil Exp $
+/* $Id: avm_a1.c,v 2.10 1998/11/15 23:54:21 keil Exp $
X 
X  * avm_a1.c     low level stuff for AVM A1 (Fritz) isdn cards
X  *
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *
X  *
X  * $Log: avm_a1.c,v $
+ * Revision 2.10  1998/11/15 23:54:21  keil
+ * changes from 2.0
+ *
+ * Revision 2.9  1998/08/13 23:36:12  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.8  1998/04/15 16:44:27  keil
+ * new init code
+ *
X  * Revision 2.7  1998/02/02 13:29:37  keil
X  * fast io
X  *
@@ -57,7 +66,7 @@
X #include "isdnl1.h"
X 
X extern const char *CardType[];
-const char *avm_revision = "$Revision: 2.7 $";
+static const char *avm_revision = "$Revision: 2.10 $";
X 
X #define	 AVM_A1_STAT_ISAC	0x01
X #define	 AVM_A1_STAT_HSCX	0x02
@@ -145,7 +154,6 @@
X {
X 	struct IsdnCardState *cs = dev_id;
X 	u_char val, sval, stat = 0;
-	char tmp[32];
X 
X 	if (!cs) {
X 		printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
@@ -155,10 +163,8 @@
X 		if (!(sval & AVM_A1_STAT_TIMER)) {
X 			byteout(cs->hw.avm.cfg_reg, 0x1E);
X 			sval = bytein(cs->hw.avm.cfg_reg);
-		} else if (cs->debug & L1_DEB_INTSTAT) {
-			sprintf(tmp, "avm IntStatus %x", sval);
-			debugl1(cs, tmp);
-		}
+		} else if (cs->debug & L1_DEB_INTSTAT)
+			debugl1(cs, "avm IntStatus %x", sval);
X 		if (!(sval & AVM_A1_STAT_HSCX)) {
X 			val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
X 			if (val) {
@@ -217,10 +223,10 @@
X 			return(request_irq(cs->irq, &avm_a1_interrupt,
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 1);
+			byteout(cs->hw.avm.cfg_reg, 0x16);
+			byteout(cs->hw.avm.cfg_reg, 0x1E);
+			inithscxisac(cs, 2);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
@@ -348,7 +354,6 @@
X 	val = bytein(cs->hw.avm.cfg_reg + 2);
X 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
X 	       cs->hw.avm.cfg_reg + 2, val);
-	byteout(cs->hw.avm.cfg_reg, 0x1E);
X 	val = bytein(cs->hw.avm.cfg_reg);
X 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
X 	       cs->hw.avm.cfg_reg, val);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/avm_a1p.c linux/drivers/isdn/hisax/avm_a1p.c
--- v2.3.3/linux/drivers/isdn/hisax/avm_a1p.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/avm_a1p.c	Sun May 23 10:03:41 1999
@@ -0,0 +1,334 @@
+/* $Id: avm_a1p.c,v 2.3 1998/11/15 23:54:22 keil Exp $
+ *
+ * avm_a1p.c    low level stuff for the following AVM cards:
+ *              A1 PCMCIA
+ *		FRITZ!Card PCMCIA
+ *		FRITZ!Card PCMCIA 2.0
+ *
+ * Author       Carsten Paeth (ca...@calle.in-berlin.de)
+ *
+ * $Log: avm_a1p.c,v $
+ * Revision 2.3  1998/11/15 23:54:22  keil
+ * changes from 2.0
+ *
+ * Revision 2.2  1998/08/13 23:36:13  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.1  1998/07/15 15:01:23  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 1.1.2.1  1998/07/15 14:43:26  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ *
+ */
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+/* register offsets */
+#define ADDRREG_OFFSET		0x02
+#define DATAREG_OFFSET		0x03
+#define ASL0_OFFSET		0x04
+#define ASL1_OFFSET		0x05
+#define MODREG_OFFSET		0x06
+#define VERREG_OFFSET		0x07
+
+/* address offsets */
+#define ISAC_FIFO_OFFSET	0x00
+#define ISAC_REG_OFFSET		0x20
+#define HSCX_CH_DIFF		0x40
+#define HSCX_FIFO_OFFSET	0x80
+#define HSCX_REG_OFFSET		0xa0
+
+/* read bits ASL0 */
+#define	 ASL0_R_TIMER		0x10 /* active low */
+#define	 ASL0_R_ISAC		0x20 /* active low */
+#define	 ASL0_R_HSCX		0x40 /* active low */
+#define	 ASL0_R_TESTBIT		0x80
+#define  ASL0_R_IRQPENDING	(ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
+
+/* write bits ASL0 */
+#define	 ASL0_W_RESET		0x01
+#define	 ASL0_W_TDISABLE	0x02
+#define	 ASL0_W_TRESET		0x04
+#define	 ASL0_W_IRQENABLE	0x08
+#define	 ASL0_W_TESTBIT		0x80
+
+/* write bits ASL1 */
+#define	 ASL1_W_LED0		0x10
+#define	 ASL1_W_LED1		0x20
+#define	 ASL1_W_ENABLE_S0	0xC0
+ 
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+static const char *avm_revision = "$Revision: 2.3 $";
+
+static inline u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	long flags;
+        u_char ret;
+
+        offset -= 0x20;
+	save_flags(flags);
+	cli();
+        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+	ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+	restore_flags(flags);
+	return ret;
+}
+
+static inline void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	long flags;
+
+        offset -= 0x20;
+
+	save_flags(flags);
+	cli();
+        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+	byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
+	restore_flags(flags);
+}
+
+static inline void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+	insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+	restore_flags(flags);
+}
+
+static inline void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+	outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+	restore_flags(flags);
+}
+
+static inline u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	u_char ret;
+	long flags;
+
+        offset -= 0x20;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+	ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+	restore_flags(flags);
+	return ret;
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 16'
echo 'File patch-2.3.4 is continued in part 17'
echo 17 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 07 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X #define _FP_WS_TYPE		signed long
X #define _FP_I_TYPE		long
X 
-/* You can optionally code some things like addition in asm. For
- * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
- * then you get a fragment of C code [if you change an #ifdef 0
- * in op-2.h] or a call to add_ssaaaa (see below).
- * Good places to look for asm fragments to use are gcc and glibc.
- * gcc's longlong.h is useful.
- */
-
-/* We need to know how to multiply and divide. If the host word size
- * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
- * codes the multiply with whatever gcc does to 'a * b'.
- * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm 
- * function that can multiply two 1W values and get a 2W result. 
- * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
- * does bitshifting to avoid overflow.
- * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
- * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or 
- * _FP_DIV_HELP_ldiv (see op-1.h).
- * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
- * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
- * to do this.]
- * In general, 'n' is the number of words required to hold the type,
- * and 't' is either S, D or Q for single/double/quad.
- *           -- PMM
- */
-/* Example: SPARC64:
- * #define _FP_MUL_MEAT_S(R,X,Y)	_FP_MUL_MEAT_1_imm(S,R,X,Y)
- * #define _FP_MUL_MEAT_D(R,X,Y)	_FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
- * #define _FP_MUL_MEAT_Q(R,X,Y)	_FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
- *
- * #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
- * #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
- * #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
- *
- * Example: i386:
- * #define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
- * #define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
- *
- * #define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
- * #define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
- */
-#define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm)
-#define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm)
-/* FIXME: This is not implemented, but should be soon */
-#define _FP_MUL_MEAT_Q(R,X,Y)   _FP_FRAC_SET_4(R, _FP_ZEROFRAC_4)
-#define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y)
-#define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
-/* FIXME: This is not implemented, but should be soon */
-#define _FP_DIV_MEAT_Q(R,X,Y)   _FP_FRAC_SET_4(R, _FP_ZEROFRAC_4)
-
-/* These macros define what NaN looks like. They're supposed to expand to 
- * a comma-separated set of 32bit unsigned ints that encode NaN.
- */
-#define _FP_NANFRAC_S		_FP_QNANBIT_S
-#define _FP_NANFRAC_D		_FP_QNANBIT_D, 0
-#define _FP_NANFRAC_Q           _FP_QNANBIT_Q, 0, 0, 0
+#define _FP_MUL_MEAT_S(R,X,Y)	_FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)	_FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)	_FP_MUL_MEAT_4_wide(Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
X 
X #define _FP_KEEPNANFRACP 1
X 
-/* This macro appears to be called when both X and Y are NaNs, and 
- * has to choose one and copy it to R. i386 goes for the larger of the
- * two, sparc64 just picks Y. I don't understand this at all so I'll
- * go with sparc64 because it's shorter :->   -- PMM 
+/* If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+/* For _Qp_* and _Q_*, this should prefer X, for
+ * CPU instruction emulation this should prefer Y.
+ * (see SPAMv9 B.2.2 section).
X  */
X #define _FP_CHOOSENAN(fs, wc, R, X, Y)				\
X   do {								\
-    R##_s = Y##_s;						\
-    _FP_FRAC_COPY_##wc(R,Y);					\
+    if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)		\
+	&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
+      {								\
+	R##_s = X##_s;						\
+	_FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    else							\
+      {								\
+	R##_s = Y##_s;						\
+	_FP_FRAC_COPY_##wc(R,Y);				\
+      }								\
X     R##_c = FP_CLS_NAN;						\
X   } while (0)
-  
-#define __FP_UNPACK_RAW_1(fs, X, val)				\
-  do {								\
-    union _FP_UNION_##fs *_flo =				\
-    	(union _FP_UNION_##fs *)val;				\
-								\
-    X##_f = _flo->bits.frac;					\
-    X##_e = _flo->bits.exp;					\
-    X##_s = _flo->bits.sign;					\
-  } while (0)
-
-#define __FP_UNPACK_RAW_2(fs, X, val)			\
-  do {							\
-    union _FP_UNION_##fs *_flo =			\
-    	(union _FP_UNION_##fs *)val;			\
-							\
-    X##_f0 = _flo->bits.frac0;				\
-    X##_f1 = _flo->bits.frac1;				\
-    X##_e  = _flo->bits.exp;				\
-    X##_s  = _flo->bits.sign;				\
-  } while (0)
-
-#define __FP_UNPACK_RAW_4(fs, X, val)			\
-  do {							\
-    union _FP_UNION_##fs *_flo =			\
-    	(union _FP_UNION_##fs *)val;			\
-							\
-    X##_f[0] = _flo->bits.frac0;			\
-    X##_f[1] = _flo->bits.frac1;			\
-    X##_f[2] = _flo->bits.frac2;			\
-    X##_f[3] = _flo->bits.frac3;			\
-    X##_e  = _flo->bits.exp;				\
-    X##_s  = _flo->bits.sign;				\
-  } while (0)
-
-#define __FP_UNPACK_S(X,val)		\
-  do {					\
-    __FP_UNPACK_RAW_1(S,X,val);		\
-    _FP_UNPACK_CANONICAL(S,1,X);	\
-  } while (0)
-
-#define __FP_UNPACK_D(X,val)		\
-  do {					\
-    __FP_UNPACK_RAW_2(D,X,val);		\
-    _FP_UNPACK_CANONICAL(D,2,X);	\
-  } while (0)
-
-#define __FP_UNPACK_Q(X,val)		\
-  do {					\
-    __FP_UNPACK_RAW_4(Q,X,val);		\
-    _FP_UNPACK_CANONICAL(Q,4,X);	\
-  } while (0)
-
-#define __FP_PACK_RAW_1(fs, val, X)				\
-  do {								\
-    union _FP_UNION_##fs *_flo =				\
-    	(union _FP_UNION_##fs *)val;				\
-								\
-    _flo->bits.frac = X##_f;					\
-    _flo->bits.exp  = X##_e;					\
-    _flo->bits.sign = X##_s;					\
-  } while (0)
-  
-#define __FP_PACK_RAW_2(fs, val, X)			\
-  do {							\
-    union _FP_UNION_##fs *_flo =			\
-    	(union _FP_UNION_##fs *)val;			\
-							\
-    _flo->bits.frac0 = X##_f0;				\
-    _flo->bits.frac1 = X##_f1;				\
-    _flo->bits.exp   = X##_e;				\
-    _flo->bits.sign  = X##_s;				\
-  } while (0)
X 
-#define __FP_PACK_RAW_4(fs, val, X)			\
-  do {							\
-    union _FP_UNION_##fs *_flo =			\
-    	(union _FP_UNION_##fs *)val;			\
-							\
-    _flo->bits.frac0 = X##_f[0];			\
-    _flo->bits.frac1 = X##_f[1];			\
-    _flo->bits.frac2 = X##_f[2];			\
-    _flo->bits.frac3 = X##_f[3];			\
-    _flo->bits.exp   = X##_e;				\
-    _flo->bits.sign  = X##_s;				\
-  } while (0)
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
+/* Some assembly to speed things up. */
+#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  __asm__ ("addcc %r7,%8,%2
+	    addxcc %r5,%6,%1
+	    addx %r3,%4,%0"						\
+	   : "=r" ((USItype)(r2)),					\
+	     "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc")
+
+#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  __asm__ ("subcc %r7,%8,%2
+	    subxcc %r5,%6,%1
+	    subx %r3,%4,%0"						\
+	   : "=r" ((USItype)(r2)),					\
+	     "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc")
+
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  do {									\
+    /* We need to fool gcc,  as we need to pass more than 10		\
+       input/outputs.  */						\
+    register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");		\
+    __asm__ __volatile__ ("
+	    addcc %r8,%9,%1
+	    addxcc %r6,%7,%0
+	    addxcc %r4,%5,%%g2
+	    addx %r2,%3,%%g1"						\
+	   : "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x3)),					\
+	     "rI" ((USItype)(y3)),					\
+	     "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc", "g1", "g2");						\
+    __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));			\
+    r3 = _t1; r2 = _t2;							\
+  } while (0)
+
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  do {									\
+    /* We need to fool gcc,  as we need to pass more than 10		\
+       input/outputs.  */						\
+    register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");		\
+    __asm__ __volatile__ ("
+	    subcc %r8,%9,%1
+	    subxcc %r6,%7,%0
+	    subxcc %r4,%5,%%g2
+	    subx %r2,%3,%%g1"						\
+	   : "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x3)),					\
+	     "rI" ((USItype)(y3)),					\
+	     "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc", "g1", "g2");						\
+    __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));			\
+    r3 = _t1; r2 = _t2;							\
+  } while (0)
+
+#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0)
+
+#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0)
+
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
+  __asm__ ("addcc %3,%4,%3
+	    addxcc %2,%%g0,%2
+	    addxcc %1,%%g0,%1
+	    addx %0,%%g0,%0"						\
+	   : "=&r" ((USItype)(x3)),					\
+	     "=&r" ((USItype)(x2)),					\
+	     "=&r" ((USItype)(x1)),					\
+	     "=&r" ((USItype)(x0))					\
+	   : "rI" ((USItype)(i)),					\
+	     "0" ((USItype)(x3)),					\
+	     "1" ((USItype)(x2)),					\
+	     "2" ((USItype)(x1)),					\
+	     "3" ((USItype)(x0))					\
+	   : "cc")
X 
-/* We only actually write to the destination register
- * if exceptions signalled (if any) will not trap.
- */
-#ifdef __SMP__
-#define __FPU_TEM \
-	(((current->tss.fsr)>>23)&0x1f)
-#else
+#ifndef __SMP__
X extern struct task_struct *last_task_used_math;
-#define __FPU_TEM \
-	(((last_task_used_math->tss.fsr)>>23)&0x1f)
X #endif
-#define __FPU_TRAP_P(bits) \
-	((__FPU_TEM & (bits)) != 0)
-
-#define __FP_PACK_S(val,X)			\
-({  int __exc = _FP_PACK_CANONICAL(S,1,X);	\
-    if(!__exc || !__FPU_TRAP_P(__exc))		\
-        __FP_PACK_RAW_1(S,val,X);		\
-    __exc;					\
-})
-
-#define __FP_PACK_D(val,X)			\
-({  int __exc = _FP_PACK_CANONICAL(D,2,X);	\
-    if(!__exc || !__FPU_TRAP_P(__exc))		\
-        __FP_PACK_RAW_2(D,val,X);		\
-    __exc;					\
-})
-
-#define __FP_PACK_Q(val,X)			\
-({  int __exc = _FP_PACK_CANONICAL(Q,4,X);	\
-    if(!__exc || !__FPU_TRAP_P(__exc))		\
-        __FP_PACK_RAW_4(Q,val,X);		\
-    __exc;					\
-})
X 
X /* Obtain the current rounding mode. */
+#ifndef FP_ROUNDMODE
X #ifdef __SMP__
X #define FP_ROUNDMODE	((current->tss.fsr >> 30) & 0x3)
X #else
X #define FP_ROUNDMODE	((last_task_used_math->tss.fsr >> 30) & 0x3)
X #endif
+#endif
X 
-/* the asm fragments go here: all these are taken from glibc-2.0.5's stdlib/longlong.h */
-
-#include <linux/types.h>
-#include <asm/byteorder.h>
-
-/* add_ssaaaa is used in op-2.h and should be equivalent to
- * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al))
- * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
- * high_addend_2, low_addend_2) adds two UWtype integers, composed by
- * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
- * respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
- * (i.e. carry out) is not stored anywhere, and is lost.
- */
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-  __asm__ ("addcc %r4,%5,%1
-        addx %r2,%3,%0"                                                 \
-           : "=r" ((USItype)(sh)),                                      \
-             "=&r" ((USItype)(sl))                                      \
-           : "%rJ" ((USItype)(ah)),                                     \
-             "rI" ((USItype)(bh)),                                      \
-             "%rJ" ((USItype)(al)),                                     \
-             "rI" ((USItype)(bl))                                       \
-           : "cc")
-
-
-/* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to
- * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al))
- * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
- * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
- * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
- * LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
- * and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
- * and is lost.
- */
-
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-  __asm__ ("subcc %r4,%5,%1
-        subx %r2,%3,%0"                                                 \
-           : "=r" ((USItype)(sh)),                                      \
-             "=&r" ((USItype)(sl))                                      \
-           : "rJ" ((USItype)(ah)),                                      \
-             "rI" ((USItype)(bh)),                                      \
-             "rJ" ((USItype)(al)),                                      \
-             "rI" ((USItype)(bl))                                       \
-           : "cc")
-
-
-/* asm fragments for mul and div */	 
-/* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
- * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
- * word product in HIGH_PROD and LOW_PROD.
- * These look ugly because the sun4/4c don't have umul/udiv/smul/sdiv in
- * hardware. 
- */
-#define umul_ppmm(w1, w0, u, v) \
-  __asm__ ("! Inlined umul_ppmm
-        wr      %%g0,%2,%%y     ! SPARC has 0-3 delay insn after a wr
-        sra     %3,31,%%g2      ! Don't move this insn
-        and     %2,%%g2,%%g2    ! Don't move this insn
-        andcc   %%g0,0,%%g1     ! Don't move this insn
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,%3,%%g1
-        mulscc  %%g1,0,%%g1
-        add     %%g1,%%g2,%0
-        rd      %%y,%1"                                                 \
-           : "=r" ((USItype)(w1)),                                      \
-             "=r" ((USItype)(w0))                                       \
-           : "%rI" ((USItype)(u)),                                      \
-             "r" ((USItype)(v))                                         \
-           : "%g1", "%g2", "cc")
-
-/* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
- * denominator) divides a UDWtype, composed by the UWtype integers
- * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
- * in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
- * than DENOMINATOR for correct operation.  If, in addition, the most
- * significant bit of DENOMINATOR must be 1, then the pre-processor symbol
- * UDIV_NEEDS_NORMALIZATION is defined to 1.
- */
-
-#define udiv_qrnnd(q, r, n1, n0, d) \
-  __asm__ ("! Inlined udiv_qrnnd
-        mov     32,%%g1
-        subcc   %1,%2,%%g0
-1:      bcs     5f
-         addxcc %0,%0,%0        ! shift n1n0 and a q-bit in lsb
-        sub     %1,%2,%1        ! this kills msb of n
-        addx    %1,%1,%1        ! so this can't give carry
-        subcc   %%g1,1,%%g1
-2:      bne     1b
-         subcc  %1,%2,%%g0
-        bcs     3f
-         addxcc %0,%0,%0        ! shift n1n0 and a q-bit in lsb
-        b       3f
-         sub    %1,%2,%1        ! this kills msb of n
-4:      sub     %1,%2,%1
-5:      addxcc  %1,%1,%1
-        bcc     2b
-         subcc  %%g1,1,%%g1
-! Got carry from n.  Subtract next step to cancel this carry.
-        bne     4b
-         addcc  %0,%0,%0        ! shift n1n0 and a 0-bit in lsb
-        sub     %1,%2,%1
-3:      xnor    %0,0,%0
-        ! End of inline udiv_qrnnd"                                     \
-           : "=&r" ((USItype) (q)),                                     \
-             "=&r" ((USItype) (r))                                      \
-           : "r" ((USItype) (d)),                                       \
-             "1" ((USItype) (n1)),                                      \
-             "0" ((USItype) (n0)) : "%g1", "cc")
-
-#define UDIV_NEEDS_NORMALIZATION 0
+/* Exception flags. */
+#define FP_EX_INVALID		(1 << 4)
+#define FP_EX_OVERFLOW		(1 << 3)
+#define FP_EX_UNDERFLOW		(1 << 2)
+#define FP_EX_DIVZERO		(1 << 1)
+#define FP_EX_INEXACT		(1 << 0)
X 
-#define abort()								\
-	return 0
+#define FP_HANDLE_EXCEPTIONS return _fex
X 
-#ifdef __BIG_ENDIAN
-#define __BYTE_ORDER __BIG_ENDIAN
+#ifdef __SMP__
+#define FP_INHIBIT_RESULTS ((current->tss.fsr >> 23) & _fex)
X #else
-#define __BYTE_ORDER __LITTLE_ENDIAN
+#define FP_INHIBIT_RESULTS ((last_task_used_math->tss.fsr >> 23) & _fex)
X #endif
X 
-/* Exception flags. */
-#define EFLAG_INVALID		(1 << 4)
-#define EFLAG_OVERFLOW		(1 << 3)
-#define EFLAG_UNDERFLOW		(1 << 2)
-#define EFLAG_DIVZERO		(1 << 1)
-#define EFLAG_INEXACT		(1 << 0)
+#endif
diff -u --recursive --new-file v2.3.3/linux/arch/sparc/math-emu/sfp-util.h linux/arch/sparc/math-emu/sfp-util.h
--- v2.3.3/linux/arch/sparc/math-emu/sfp-util.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/math-emu/sfp-util.h	Sat May 29 11:09:04 1999
@@ -0,0 +1,115 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) 				\
+  __asm__ ("addcc %r4,%5,%1
+	addx %r2,%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%rJ" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "%rJ" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl))					\
+	   : "cc")
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) 				\
+  __asm__ ("subcc %r4,%5,%1
+	subx %r2,%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "rJ" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "rJ" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl))					\
+	   : "cc")
+
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("! Inlined umul_ppmm
+	wr	%%g0,%2,%%y	! SPARC has 0-3 delay insn after a wr
+	sra	%3,31,%%g2	! Don't move this insn
+	and	%2,%%g2,%%g2	! Don't move this insn
+	andcc	%%g0,0,%%g1	! Don't move this insn
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,0,%%g1
+	add	%%g1,%%g2,%0
+	rd	%%y,%1"							\
+	   : "=r" ((USItype)(w1)),					\
+	     "=r" ((USItype)(w0))					\
+	   : "%rI" ((USItype)(u)),					\
+	     "r" ((USItype)(v))						\
+	   : "%g1", "%g2", "cc")
+
+/* It's quite necessary to add this much assembler for the sparc.
+   The default udiv_qrnnd (in C) is more than 10 times slower!  */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("! Inlined udiv_qrnnd
+	mov	32,%%g1
+	subcc	%1,%2,%%g0
+1:	bcs	5f
+	 addxcc %0,%0,%0	! shift n1n0 and a q-bit in lsb
+	sub	%1,%2,%1	! this kills msb of n
+	addx	%1,%1,%1	! so this can't give carry
+	subcc	%%g1,1,%%g1
+2:	bne	1b
+	 subcc	%1,%2,%%g0
+	bcs	3f
+	 addxcc %0,%0,%0	! shift n1n0 and a q-bit in lsb
+	b	3f
+	 sub	%1,%2,%1	! this kills msb of n
+4:	sub	%1,%2,%1
+5:	addxcc	%1,%1,%1
+	bcc	2b
+	 subcc	%%g1,1,%%g1
+! Got carry from n.  Subtract next step to cancel this carry.
+	bne	4b
+	 addcc	%0,%0,%0	! shift n1n0 and a 0-bit in lsb
+	sub	%1,%2,%1
+3:	xnor	%0,0,%0
+	! End of inline udiv_qrnnd"					\
+	   : "=&r" ((USItype)(q)),					\
+	     "=&r" ((USItype)(r))					\
+	   : "r" ((USItype)(d)),					\
+	     "1" ((USItype)(n1)),					\
+	     "0" ((USItype)(n0)) : "%g1", "cc")
+#define UDIV_NEEDS_NORMALIZATION 0
+
+#define abort()								\
+	return 0
+
+#ifdef __BIG_ENDIAN
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.3/linux/arch/sparc64/defconfig	Mon May 17 09:55:21 1999
+++ linux/arch/sparc64/defconfig	Mon May 31 22:08:10 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)
@@ -156,6 +157,10 @@
X # CONFIG_IPX_INTERN is not set
X # CONFIG_SPX is not set
X CONFIG_ATALK=m
+CONFIG_DECNET=m
+CONFIG_DECNET_SIOCGIFCONF=y
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_DECNET_RAW=y
X # CONFIG_X25 is not set
X # CONFIG_LAPB is not set
X # CONFIG_BRIDGE is not set
@@ -310,6 +315,7 @@
X # CONFIG_MAC_PARTITION is not set
X CONFIG_SMD_DISKLABEL=y
X CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_SGI_DISKLABEL is not set
X # CONFIG_UNIXWARE_DISKLABEL is not set
X CONFIG_AMIGA_PARTITION=y
X CONFIG_NLS=y
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S
--- v2.3.3/linux/arch/sparc64/kernel/etrap.S	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/kernel/etrap.S	Thu May 27 09:55:21 1999
@@ -1,8 +1,8 @@
-/* $Id: etrap.S,v 1.40 1998/06/12 14:54:03 jj Exp $
+/* $Id: etrap.S,v 1.41 1999/05/25 16:53:09 jj Exp $
X  * etrap.S: Preparing for entry into the kernel on Sparc V9.
X  *
X  * Copyright (C) 1996, 1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1997, 1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997, 1998, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X  */
X 
X #include <asm/asi.h>
@@ -59,10 +59,9 @@
X 		stb			%l5, [%l6 + AOFF_task_tss + AOFF_thread_fpdepth]	! Store
X 		wrpr			%g3, 0, %otherwin					! Single	Group+4bubbles
X 		wrpr			%g2, 0, %wstate						! Single	Group+4bubbles
-		ldxa			[%l4] ASI_DMMU, %g2					! Load		Group
X 		stxa			%g0, [%l4] ASI_DMMU					! Store		Group
-		stxa			%g2, [%l4 + %l4] ASI_DMMU				! Store		Group
X 		flush			%l6							! Single	Group+9bubbles
+		wr			%g0, ASI_AIUS, %asi					! Single	Group+4bubbles
X 2:		wrpr			%g0, 0x0, %tl						! Single	Group+4bubbles
X 		andn			%g1, PSTATE_MM, %l1					! IEU0		Group
X 		mov			%g4, %l4						! IEU1
@@ -135,10 +134,9 @@
X 		sll			%g2, 3, %g2						! IEU0		Group
X 		wrpr			%g3, 0, %otherwin					! Single	Group+4bubbles
X 		wrpr			%g2, 0, %wstate						! Single	Group+4bubbles
-		ldxa			[%l4] ASI_DMMU, %g2					! Load		Group
X 		stxa			%g0, [%l4] ASI_DMMU					! Store		Group
-		stxa			%g2, [%l4 + %l4] ASI_DMMU				! Store		Group
X 		flush			%l6							! Single	Group+9bubbles
+		wr			%g0, ASI_AIUS, %asi					! Single	Group+4bubbles
X 2:		wrpr			%g0, 0x0, %tl						! Single	Group+4bubbles
X 		andn			%g1, PSTATE_MM, %l1					! IEU0		Group
X 		mov			%g4, %l4						! IEU1
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- v2.3.3/linux/arch/sparc64/kernel/head.S	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/kernel/head.S	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.60 1999/04/12 08:08:21 davem Exp $
+/* $Id: head.S,v 1.61 1999/05/25 16:53:10 jj Exp $
X  * head.S: Initial boot code for the Sparc64 port of Linux.
X  *
X  * Copyright (C) 1996,1997 David S. Miller (da...@caip.rutgers.edu)
@@ -286,6 +286,7 @@
X 	wr	%g6, 0x0, %pic
X #endif
X 
+	wr	%g0, ASI_P, %asi
X 	mov	1, %g5
X 	sllx	%g5, (PAGE_SHIFT + 1), %g5
X 	sub	%g5, (REGWIN_SZ + STACK_BIAS), %g5
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.3.3/linux/arch/sparc64/kernel/process.c	Tue May 11 08:24:32 1999
+++ linux/arch/sparc64/kernel/process.c	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.92 1999/05/08 23:04:48 davem Exp $
+/*  $Id: process.c,v 1.94 1999/05/27 04:49:30 davem Exp $
X  *  arch/sparc64/kernel/process.c
X  *
X  *  Copyright (C) 1995, 1996 David S. Miller (da...@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- v2.3.3/linux/arch/sparc64/kernel/ptrace.c	Wed Mar 24 15:10:28 1999
+++ linux/arch/sparc64/kernel/ptrace.c	Sat May 22 12:42:04 1999
@@ -603,6 +603,7 @@
X 		if((!child->dumpable ||
X 		    (current->uid != child->euid) ||
X 		    (current->uid != child->uid) ||
+		    (current->uid != child->suid) ||
X 		    (current->gid != child->egid) ||
X 		    (current->gid != child->sgid) ||
X 		    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- v2.3.3/linux/arch/sparc64/kernel/rtrap.S	Mon Nov 16 10:37:28 1998
+++ linux/arch/sparc64/kernel/rtrap.S	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.45 1998/11/09 15:33:29 davem Exp $
+/* $Id: rtrap.S,v 1.46 1999/05/25 16:53:20 jj Exp $
X  * rtrap.S: Preparing for return from trap on Sparc V9.
X  *
X  * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -106,7 +106,6 @@
X 		brnz,pn			%l3, kern_rtt
X 		 mov			PRIMARY_CONTEXT, %l7
X 		stxa			%l0, [%l7] ASI_DMMU
-		stxa			%l0, [%l7 + %l7] ASI_DMMU
X 		flush			%o5
X 		rdpr			%wstate, %l1
X 
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.3.3/linux/arch/sparc64/kernel/setup.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/kernel/setup.c	Sat May 29 11:09:04 1999
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $
+/*  $Id: setup.c,v 1.44 1999/05/28 02:17:29 davem Exp $
X  *  linux/arch/sparc64/kernel/setup.c
X  *
X  *  Copyright (C) 1995,1996  David S. Miller (da...@caip.rutgers.edu)
@@ -550,7 +550,9 @@
X 			ic_servaddr = sv;
X 			if (gw)
X 				ic_gateway = gw;
+#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
X 			ic_proto_enabled = 0;
+#endif
X 		}
X 	}
X #endif
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.3.3/linux/arch/sparc64/kernel/smp.c	Tue May 11 08:24:32 1999
+++ linux/arch/sparc64/kernel/smp.c	Thu May 27 09:55:21 1999
@@ -272,25 +272,26 @@
X static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, unsigned long cpu)
X {
X 	u64 result, target = (cpu << 14) | 0x70;
-	int stuck;
+	int stuck, tmp;
X 
X #ifdef XCALL_DEBUG
X 	printk("CPU[%d]: xcall(data[%016lx:%016lx:%016lx],tgt[%016lx])\n",
X 	       smp_processor_id(), data0, data1, data2, target);
X #endif
X again:
+	tmp = 0x40;
X 	__asm__ __volatile__("
-	wrpr	%0, %1, %%pstate
-	wr	%%g0, %2, %%asi
-	stxa	%3, [0x40] %%asi
-	stxa	%4, [0x50] %%asi
-	stxa	%5, [0x60] %%asi
+	wrpr	%1, %2, %%pstate
+	stxa	%4, [%0] %3
+	stxa	%5, [%0+%8] %3
+	add	%0, %8, %0
+	stxa	%6, [%0+%8] %3
X 	membar	#Sync
-	stxa	%%g0, [%6] %%asi
+	stxa	%%g0, [%7] %3
X 	membar	#Sync"
-	: /* No outputs */
+	: "=r" (tmp)
X 	: "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
-	  "r" (data0), "r" (data1), "r" (data2), "r" (target));
+	  "r" (data0), "r" (data1), "r" (data2), "r" (target), "r" (0x10), "0" (tmp));
X 
X 	/* NOTE: PSTATE_IE is still clear. */
X 	stuck = 100000;
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.3/linux/arch/sparc64/kernel/sys_sunos32.c	Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon May 24 13:03:49 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.22 1998/10/26 20:01:13 davem Exp $
+/* $Id: sys_sunos32.c,v 1.25 1999/05/24 19:40:44 davem Exp $
X  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
X  *
X  * Copyright (C) 1995, 1996, 1997 David S. Miller (da...@caip.rutgers.edu)
@@ -1347,7 +1347,7 @@
X 
X 	lock_kernel();
X 	ret = check_nonblock(sys32_readv(fd, vector, count), fd);
-	lock_kernel();
+	unlock_kernel();
X 	return ret;
X }
X 
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S
--- v2.3.3/linux/arch/sparc64/kernel/trampoline.S	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/kernel/trampoline.S	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: trampoline.S,v 1.8 1998/12/09 21:01:15 davem Exp $
+/* $Id: trampoline.S,v 1.9 1999/05/25 16:53:12 jj Exp $
X  * trampoline.S: Jump start slave processors on sparc64.
X  *
X  * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
@@ -130,6 +130,8 @@
X 	 nop
X 
X bounce:
+	wr	%g0, ASI_P, %asi
+
X 	mov	PRIMARY_CONTEXT, %g7
X 	stxa	%g0, [%g7] ASI_DMMU
X 	membar	#Sync
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.3.3/linux/arch/sparc64/kernel/traps.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/kernel/traps.c	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.58 1999/03/29 12:38:10 jj Exp $
+/* $Id: traps.c,v 1.59 1999/05/18 16:57:10 jj Exp $
X  * arch/sparc64/kernel/traps.c
X  *
X  * Copyright (C) 1995,1997 David S. Miller (da...@caip.rutgers.edu)
@@ -452,15 +452,35 @@
X 	if((((unsigned long) pc) & 3))
X 		return;
X 
+	printk("Instruction DUMP:");
X 	for(i = -3; i < 6; i++)
X 		printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
X 	printk("\n");
X }
X 
+void user_instruction_dump (unsigned int *pc)
+{
+	int i;
+	unsigned int buf[9];
+	
+	if((((unsigned long) pc) & 3))
+		return;
+		
+	if(copy_from_user(buf, pc - 3, sizeof(buf)))
+		return;
+
+	printk("Instruction DUMP:");
+	for(i = 0; i < 9; i++)
+		printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
+	printk("\n");
+}
+
X void die_if_kernel(char *str, struct pt_regs *regs)
X {
X 	extern void __show_regs(struct pt_regs * regs);
X 	extern void smp_report_regs(void);
+	int count = 0;
+	struct reg_window *lastrw;
X 	
X 	/* Amuse the user. */
X 	printk(
@@ -472,25 +492,28 @@
X 	printk("%s(%d): %s\n", current->comm, current->pid, str);
X 	__asm__ __volatile__("flushw");
X 	__show_regs(regs);
-	{
+	if(regs->tstate & TSTATE_PRIV) {
X 		struct reg_window *rw = (struct reg_window *)
X 			(regs->u_regs[UREG_FP] + STACK_BIAS);
X 
X 		/* Stop the back trace when we hit userland or we
X 		 * find some badly aligned kernel stack.
X 		 */
+		lastrw = (struct reg_window *)current;
X 		while(rw					&&
-		      (((unsigned long) rw) >= PAGE_OFFSET)	&&
+		      count++ < 30				&&
+		      rw >= lastrw				&&
+		      (char *) rw < ((char *) current)
+		        + sizeof (union task_union) 		&&
X 		      !(((unsigned long) rw) & 0x7)) {
X 			printk("Caller[%016lx]\n", rw->ins[7]);
+			lastrw = rw;
X 			rw = (struct reg_window *)
X 				(rw->ins[6] + STACK_BIAS);
X 		}
-	}
-	if(regs->tstate & TSTATE_PRIV) {
-		printk("Instruction DUMP:");
X 		instruction_dump ((unsigned int *) regs->tpc);
-	}
+	} else
+		user_instruction_dump ((unsigned int *) regs->tpc);
X #ifdef __SMP__
X 	smp_report_regs();
X #endif
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c
--- v2.3.3/linux/arch/sparc64/kernel/unaligned.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/kernel/unaligned.c	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.15 1999/04/03 11:36:21 anton Exp $
+/* $Id: unaligned.c,v 1.16 1999/05/25 16:53:15 jj Exp $
X  * unaligned.c: Unaligned load/store trap handling with special
X  *              cases for the kernel to do them more quickly.
X  *
@@ -228,7 +228,8 @@
X 	"sra	%%g7, 0, %%g7\n\t"						\
X 	"stx	%%l1, [%0]\n\t"							\
X 	"stx	%%g7, [%0 + 8]\n"						\
-"0:\n\n\t"									\
+"0:\n\t"									\
+	"wr	%%g0, %5, %%asi\n\n\t"						\
X 	".section __ex_table\n\t"						\
X 	".word	4b, " #errh "\n\t"						\
X 	".word	5b, " #errh "\n\t"						\
@@ -244,7 +245,8 @@
X 	".word	15b, " #errh "\n\t"						\
X 	".word	16b, " #errh "\n\n\t"						\
X 	".previous\n\t"								\
-	: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), "r" (asi)	\
+	: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed),		\
+	  "r" (asi), "i" (ASI_AIUS)						\
X 	: "l1", "l2", "g7", "g1", "cc");					\
X })
X 	
@@ -282,7 +284,8 @@
X "2:\t"	"srl	%%l1, 8, %%l2\n"						\
X "16:\t"	"stba	%%l2, [%0] %%asi\n"						\
X "17:\t"	"stba	%%l1, [%0 + 1] %%asi\n"						\
-"0:\n\n\t"									\
+"0:\n\t"									\
+	"wr	%%g0, %4, %%asi\n\n\t"						\
X 	".section __ex_table\n\t"						\
X 	".word	4b, " #errh "\n\t"						\
X 	".word	5b, " #errh "\n\t"						\
@@ -299,7 +302,7 @@
X 	".word	16b, " #errh "\n\t"						\
X 	".word	17b, " #errh "\n\n\t"						\
X 	".previous\n\t"								\
-	: : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi)		\
+	: : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi), "i" (ASI_AIUS)\
X 	: "l1", "l2", "g7", "g1", "cc");					\
X })
X 
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/VIS.h linux/arch/sparc64/lib/VIS.h
--- v2.3.3/linux/arch/sparc64/lib/VIS.h	Mon Jul  7 08:18:55 1997
+++ linux/arch/sparc64/lib/VIS.h	Thu May 27 09:55:21 1999
@@ -1,9 +1,9 @@
-/* $Id: VIS.h,v 1.3 1997/06/27 14:53:18 jj Exp $
+/* $Id: VIS.h,v 1.4 1999/05/25 16:52:50 jj Exp $
X  * VIS.h: High speed copy/clear operations utilizing the UltraSparc
X  *        Visual Instruction Set.
X  *
X  * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1996, 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996, 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X  */
X 
X 	/* VIS code can be used for numerous copy/set operation variants.
@@ -28,6 +28,8 @@
X #include <asm/head.h>
X #include <asm/asi.h>
X #else
+#define ASI_AIUS		0x11 /* Secondary, user				*/
+#define ASI_BLK_AIUS		0x71 /* Secondary, user, blk ld/st		*/
X #define ASI_P			0x80 /* Primary, implicit			*/
X #define ASI_S			0x81 /* Secondary, implicit			*/
X #define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit		*/
@@ -43,15 +45,28 @@
X 	 * cell exchange program...
X 	 */
X #define ASI_BLK_XOR		(ASI_P ^ ASI_BLK_P)
+	/* Well, things get more hairy if we use ASI_AIUS as
+	 * USER_DS and ASI_P as KERNEL_DS, we'd reach
+	 * commit block stores this way which is not what we want...
+	 */
+	/* ASI_P->ASI_BLK_P && ASI_AIUS->ASI_BLK_AIUS transitions can be done
+	 * as blkasi = asi | ASI_BLK_OR
+	 */
+#define ASI_BLK_OR		(ASI_BLK_P & ~ASI_P)
+	/* Transition back from ASI_BLK_P->ASI_P && ASI_BLK_AIUS->ASI_AIUS is
+	 * more complicated:
+	 * asi = blkasi ^ (blkasi >> 3) ^ ASI_BLK_XOR1
+	 */
+#define ASI_BLK_XOR1		(ASI_BLK_P ^ (ASI_BLK_P >> 3) ^ ASI_P)
X 
X #define	asi_src			%o3
X #define asi_dest		%o4
X 
X #ifdef __KERNEL__
X #define ASI_SETSRC_BLK		wr	asi_src, 0, %asi;
-#define ASI_SETSRC_NOBLK	wr	asi_src, ASI_BLK_XOR, %asi;
+#define ASI_SETSRC_NOBLK	wr	asi_src, 0, %asi;
X #define ASI_SETDST_BLK		wr	asi_dest, 0, %asi;
-#define ASI_SETDST_NOBLK	wr	asi_dest, ASI_BLK_XOR, %asi;
+#define ASI_SETDST_NOBLK	wr	asi_dest, 0, %asi;
X #define ASIBLK			%asi
X #define ASINORMAL		%asi
X #define LDUB			lduba
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/VISbzero.S linux/arch/sparc64/lib/VISbzero.S
--- v2.3.3/linux/arch/sparc64/lib/VISbzero.S	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/lib/VISbzero.S	Thu May 27 09:55:21 1999
@@ -1,9 +1,9 @@
-/* $Id: VISbzero.S,v 1.9 1998/06/12 14:53:50 jj Exp $
+/* $Id: VISbzero.S,v 1.10 1999/05/25 16:52:56 jj Exp $
X  * VISbzero.S: High speed clear operations utilizing the UltraSparc
X  *        Visual Instruction Set.
X  *
X  * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1996, 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996, 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X  */
X 
X #include "VIS.h"
@@ -84,9 +84,14 @@
X 	.align		32
X #ifdef __KERNEL__
X 	.globl		__bzero, __bzero_noasi
+__bzero_noasi:
+	rd		%asi, %g5
+	ba,pt		%xcc, __bzero+12
+	 mov		%g5, %o4
X __bzero:
+	rd		%asi, %g5
X 	wr		%g0, ASI_P, %asi		! LSU	Group
-__bzero_noasi:
+	mov		ASI_P, %o4
X #else
X 	.globl		bzero
X bzero_private:
@@ -143,8 +148,8 @@
X 6:	andncc		%o1, 0x3f, %o3
X 7:	be,pn		%xcc, 9f
X #ifdef __KERNEL__
-	 rd		%asi, %o4
-	wr		%o4, ASI_BLK_XOR, %asi
+	 or		%o4, ASI_BLK_OR, %g7 
+	wr		%g7, %g0, %asi
X 	VISEntryHalf
X #else
X 	 wr		%g0, ASI_BLK_P, %asi
@@ -221,7 +226,11 @@
X 	add		%o0, 2, %o0
X 1:	bne,a,pn	%xcc, 8f
X 	 EX(STB		%g0, [%o0] ASINORMAL, add %g0, 1)
-8:	retl
+8:
+#ifdef __KERNEL__
+	wr		%g5, %g0, %asi
+#endif
+	retl
X 	 RETL
X 17:	be,pn		%xcc, 13b
X 	 orcc		%o1, 0, %g0
@@ -230,7 +239,11 @@
X 	subcc		%o1, 1, %o1
X 	bne,pt		%xcc, 8b
X 	 EX(STB		%g0, [%o0 - 1] ASINORMAL, add %o1, 1)
-0:	retl
+0:
+#ifdef __KERNEL__
+	wr		%g5, %g0, %asi
+#endif
+	retl
X 	 RETL
X 
X #ifdef __KERNEL__
@@ -239,6 +252,7 @@
X VISbzerofixup_reto1:
X 	mov		%o1, %o0
X VISbzerofixup_ret0:
+	wr		%g5, %g0, %asi
X 	retl
X 	 wr		%g0, 0, %fprs
X VISbzerofixup_ret1:
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S
--- v2.3.3/linux/arch/sparc64/lib/VIScopy.S	Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc64/lib/VIScopy.S	Thu May 27 09:55:21 1999
@@ -1,9 +1,9 @@
-/* $Id: VIScopy.S,v 1.19 1998/10/19 21:52:19 davem Exp $
+/* $Id: VIScopy.S,v 1.20 1999/05/25 16:52:57 jj Exp $
X  * VIScopy.S: High speed copy operations utilizing the UltraSparc
X  *            Visual Instruction Set.
X  *
X  * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1996, 1997, 1998 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X  */
X 
X #include "VIS.h"
@@ -26,18 +26,25 @@
X #ifdef __KERNEL__
X 
X #include <asm/visasm.h>
+#include <asm/asm_offsets.h>
X 
-#define FPU_CLEAN_RETL				\
-	VISExit					\
-	retl;					\
-	 clr		%o0;
-#define FPU_RETL				\
-	VISExit					\
-	retl;					\
-	 clr		%o0;
-#define NORMAL_RETL				\
-	retl;					\
-	 clr		%o0;
+#define FPU_CLEAN_RETL								\
+	ldub		[%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1;	\
+	VISExit									\
+	clr		%o0;							\
+	retl;									\
+	 wr		%o1, %g0, %asi;
+#define FPU_RETL								\
+	ldub		[%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1;	\
+	VISExit									\
+	clr		%o0;							\
+	retl;									\
+	 wr		%o1, %g0, %asi;
+#define NORMAL_RETL								\
+	ldub		[%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1;	\
+	clr		%o0;							\
+	retl;									\
+	 wr		%o1, %g0, %asi;
X #define EX(x,y,a,b) 				\
X 98: 	x,y;					\
X 	.section .fixup;			\
@@ -146,10 +153,20 @@
X 	EXVIS(STBLK		%fsrc, [%dest] ASIBLK);		\
X 	add			%dest, 0x40, %dest;
X 
+#ifdef __KERNEL__
X #define STORE_JUMP(dest, fsrc, target)				\
+	srl			asi_dest, 3, %g5;		\
X 	EXVIS3(STBLK		%fsrc, [%dest] ASIBLK);		\
+	xor		       asi_dest, ASI_BLK_XOR1, asi_dest;\
X 	add			%dest, 0x40, %dest;		\
+	xor			asi_dest, %g5, asi_dest;	\
X 	ba,pt			%xcc, target;
+#else
+#define STORE_JUMP(dest, fsrc, target)				\
+	EXVIS3(STBLK		%fsrc, [%dest] ASIBLK);		\
+	add			%dest, 0x40, %dest;		\
+	ba,pt			%xcc, target;
+#endif
X 
X #ifndef __KERNEL__
X #define VISLOOP_PAD nop; nop; nop; nop; \
@@ -157,9 +174,7 @@
X 		    nop; nop; nop; nop; \
X 		    nop; nop; nop;
X #else
-#define VISLOOP_PAD nop; nop; nop; nop; \
-		    nop; nop; nop; nop; \
-		    nop;
+#define VISLOOP_PAD
X #endif
X 
X #define FINISH_VISCHUNK(dest, f0, f1, left)			\
@@ -170,11 +185,13 @@
X 	EXVIS4(STDF		%f48, [%dest] ASINORMAL);	\
X 	add			%dest, 8, %dest;
X 
-#define UNEVEN_VISCHUNK(dest, f0, f1, left)			\
+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)		\
X 	subcc			%left, 8, %left;		\
X 	bl,pn			%xcc, vis_out;			\
-	 fsrc1			%f0, %f1;			\
-	ba,a,pt			%xcc, vis_slk;
+	 fsrc1			%f0, %f1;
+#define UNEVEN_VISCHUNK(dest, f0, f1, left)			\
+	UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)		\
+	ba,a,pt			%xcc, vis_out_slk;
X 
X 	/* Macros for non-VIS memcpy code. */
X #ifdef REGS_64BIT
@@ -303,32 +320,32 @@
X 		.type			__memcpy_entry,@function
X memcpy_private:
X __memcpy:
-memcpy:		mov		ASI_BLK_P, asi_src		! IEU0	Group
+memcpy:		mov		ASI_P, asi_src			! IEU0	Group
X 		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_BLK_P, asi_dest		! IEU1
+		 mov		ASI_P, asi_dest			! IEU1
X 		retl
X 		 clr		%o0
X 
X 		.align			32
X 		.globl			__copy_from_user
X 		.type			__copy_from_user,@function
-__copy_from_user:mov		ASI_BLK_S, asi_src		! IEU0	Group
+__copy_from_user:rd		%asi, asi_src			! IEU0	Group
X 		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_BLK_P, asi_dest		! IEU1
+		 mov		ASI_P, asi_dest			! IEU1
X 
X 		.globl			__copy_to_user
X 		.type			__copy_to_user,@function
-__copy_to_user:	mov		ASI_BLK_P, asi_src		! IEU0	Group
+__copy_to_user:	mov		ASI_P, asi_src			! IEU0	Group
X 		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_BLK_S, asi_dest		! IEU1
+		 rd		%asi, asi_dest			! IEU1
X 		retl						! CTI	Group
X 		 clr		%o0				! IEU0	Group
X 
X 		.globl			__copy_in_user
X 		.type			__copy_in_user,@function
-__copy_in_user:	mov		ASI_BLK_S, asi_src		! IEU0	Group
+__copy_in_user:	rd		%asi, asi_src			! IEU0	Group
X 		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_BLK_S, asi_dest		! IEU1
+		 mov		asi_src, asi_dest		! IEU1
X 		retl						! CTI	Group
X 		 clr		%o0				! IEU0	Group
X #endif
@@ -446,6 +463,10 @@
X 	fmovd			%f0, %f2			! FPU
X 	sub			%g3, 0x10, %g3			! IEU0	Group
X 	sub			%o2, %g7, %o2			! IEU1
+#ifdef __KERNEL__
+	or			asi_src, ASI_BLK_OR, asi_src	! IEU0	Group
+	or			asi_dest, ASI_BLK_OR, asi_dest	! IEU1
+#endif
X 	alignaddr		%g1, %g0, %g0			! GRU	Group
X 	add			%g1, %g7, %g1			! IEU0	Group
X 	subcc			%o2, %g3, %o2			! IEU1
@@ -584,7 +605,13 @@
X finish_f40:	FINISH_VISCHUNK(o0, f40, f42, g3)
X finish_f42:	FINISH_VISCHUNK(o0, f42, f44, g3)
X finish_f44:	FINISH_VISCHUNK(o0, f44, f46, g3)
-finish_f46:	UNEVEN_VISCHUNK(o0, f46, f0,  g3)
+finish_f46:	UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
+vis_out_slk:
+#ifdef __KERNEL__
+	srl		asi_src, 3, %g5				! IEU0	Group
+	xor		asi_src, ASI_BLK_XOR1, asi_src		! IEU1
+	xor		asi_src, %g5, asi_src			! IEU0	Group
+#endif
X vis_slk:ASI_SETSRC_NOBLK					! LSU	Group
X 	EXVIS4(LDDF	[%o1] ASINORMAL, %f2)			! Load	Group
X 	add		%o1, 8, %o1				! IEU0
@@ -592,7 +619,7 @@
X 	ASI_SETDST_NOBLK					! LSU	Group
X 	faligndata	%f0, %f2, %f8				! GRU	Group
X 	EXVIS5(STDF	%f8, [%o0] ASINORMAL)			! Store
-	bl,pn		%xcc, vis_out				! CTI
+	bl,pn		%xcc, vis_out_slp			! CTI
X 	 add		%o0, 8, %o0				! IEU0	Group
X 	ASI_SETSRC_NOBLK					! LSU	Group
X 	EXVIS4(LDDF	[%o1] ASINORMAL, %f0)			! Load	Group
@@ -603,8 +630,20 @@
X 	EXVIS5(STDF	%f8, [%o0] ASINORMAL)			! Store
X 	bge,pt		%xcc, vis_slk				! CTI
X 	 add		%o0, 8, %o0				! IEU0	Group
+vis_out_slp:
+#ifdef __KERNEL__
+	brz,pt		%o2, vis_ret				! CTI	Group
+	 mov		%g1, %o1				! IEU0
+	ba,pt		%xcc, vis_slp+4				! CTI	Group
+	 ASI_SETSRC_NOBLK					! LSU	Group
+#endif
X vis_out:brz,pt		%o2, vis_ret				! CTI	Group
X 	 mov		%g1, %o1				! IEU0
+#ifdef __KERNEL__
+	srl		asi_src, 3, %g5				! IEU0	Group
+	xor		asi_src, ASI_BLK_XOR1, asi_src		! IEU1
+	xor		asi_src, %g5, asi_src			! IEU0	Group
+#endif
X vis_slp:ASI_SETSRC_NOBLK					! LSU	Group
X 	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
X 	add		%o1, 1, %o1				! IEU0
@@ -970,11 +1009,13 @@
X 		/* If this is copy_from_user(), zero out the rest of the
X 		 * kernel buffer.
X 		 */
+		ldub		[%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o4
X 		andcc		asi_src, 0x1, %g0
X 		be,pt		%icc, 1f
-		 andcc		asi_dest, 0x1, %g0
-		bne,pn		%icc, 1f
X 		 VISExit
+		andcc		asi_dest, 0x1, %g0
+		bne,pn		%icc, 1f
+		 nop
X 		save		%sp, -160, %sp
X 		mov		%i0, %o0
X 		call		__bzero
@@ -982,7 +1023,7 @@
X 		restore
X 1:		mov		%o1, %o0
X 		retl
-		 nop
+		 wr		%o4, %g0, %asi
X VIScopyfixup1:	subcc		%g2, 18, %g2
X 		add		%o0, 32, %o0
X 		bgeu,a,pt	%icc, VIScopyfixup1
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/VIScsum.S linux/arch/sparc64/lib/VIScsum.S
--- v2.3.3/linux/arch/sparc64/lib/VIScsum.S	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/lib/VIScsum.S	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: VIScsum.S,v 1.3 1998/06/12 14:53:57 jj Exp $
+/* $Id: VIScsum.S,v 1.4 1999/05/25 16:53:00 jj Exp $
X  * VIScsum.S: High bandwidth IP checksumming utilizing the UltraSparc
X  *            Visual Instruction Set.
X  *
@@ -27,6 +27,7 @@
X #include <asm/head.h>
X #include <asm/asi.h>
X #include <asm/visasm.h>
+#include <asm/asm_offsets.h>
X #else
X #define ASI_BLK_P	0xf0
X #define FRPS_FEF	0x04
@@ -339,9 +340,13 @@
X 	membar		#Sync			/*  LSU		Group			*/
X 	DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14)
X 	END_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30)
+#ifdef __KERNEL__
+	ldub		[%g6 + AOFF_task_tss + AOFF_thread_current_ds], %g7
+#endif
X 	and		%o1, 0x3f, %o1		/*  IEU0	Group			*/
X #ifdef __KERNEL__
X 	VISExit
+	wr		%g7, %g0, %asi
X #endif
X 20:	andcc		%o1, 0xf0, %g1		/*  IEU1	Group			*/
X 	be,pn		%icc, 23f		/*  CTI					*/
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/VIScsumcopy.S linux/arch/sparc64/lib/VIScsumcopy.S
--- v2.3.3/linux/arch/sparc64/lib/VIScsumcopy.S	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/lib/VIScsumcopy.S	Thu May 27 09:55:21 1999
@@ -1,8 +1,8 @@
-/* $Id: VIScsumcopy.S,v 1.5 1998/06/12 14:53:48 jj Exp $
+/* $Id: VIScsumcopy.S,v 1.6 1999/05/25 16:53:03 jj Exp $
X  * VIScsumcopy.S: High bandwidth IP checksumming with simultaneous
X  *            copying utilizing the UltraSparc Visual Instruction Set.
X  *
- * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X  *
X  * Based on older sparc32/sparc64 checksum.S, which is:
X  *
@@ -28,14 +28,17 @@
X #include <asm/asi.h>
X #include <asm/page.h>
X #include <asm/visasm.h>
+#define ASI_BLK_XOR	0
+#define ASI_BLK_XOR1	(ASI_BLK_P ^ (ASI_BLK_P >> 3) ^ ASI_P)
+#define ASI_BLK_OR	(ASI_BLK_P & ~ASI_P)
X #else
X #define ASI_P		0x80
X #define ASI_BLK_P	0xf0
X #define FRPS_FEF	0x04
X #define FPRS_DU		0x02
X #define FPRS_DL		0x01
-#endif
X #define ASI_BLK_XOR	(ASI_BLK_P ^ ASI_P)
+#endif
X 
X #define src		o0
X #define dst		o1
@@ -244,7 +247,7 @@
X 	.text
X 	.globl		csum_partial_copy_vis
X 	.align		32
-/* %asi should be either ASI_P or ASI_S for csum_partial_copy resp. csum_partial_copy_from_user */
+/* %asi should be either ASI_P or ASI_AIUS for csum_partial_copy resp. csum_partial_copy_from_user */
X /* This assumes that !((%src^%dst)&3) && !((%src|%dst)&1) && %len >= 256 */
X csum_partial_copy_vis:
X 	andcc		%dst, 7, %g0		/*  IEU1	Group			*/
@@ -368,6 +371,7 @@
X 3:	rd		%asi, %g2		/*  LSU		Group + 4 bubbles	*/
X #ifdef __KERNEL__
X 4:	sethi		%hi(vis0s), %g7		/*  IEU0	Group			*/
+	or		%g2, ASI_BLK_OR, %g2	/*  IEU1				*/
X #else
X 4:	rd		%pc, %g7		/*  LSU		Group + 4 bubbles	*/
X #endif
@@ -775,18 +779,24 @@
X e1:	END_THE_TRICK1(	f0,f2,f4,f6,f8,f10,f12,f14,f16,f6)
X e2:	END_THE_TRICK1(	f16,f18,f20,f22,f24,f26,f28,f30,f32,f6)
X e3:	END_THE_TRICK1(	f32,f34,f36,f38,f40,f42,f44,f46,f0,f6)
-ett:	rd		%gsr, %x3		/*  LSU		Group+4bubbles		*/
+ett:	rd		%asi, %x4		/*  LSU		Group+4bubbles		*/
+	rd		%gsr, %x3		/*  LSU		Group+4bubbles		*/
+#ifdef __KERNEL__
+	srl		%x4, 3, %x5		/*  IEU0	Group			*/
+	xor		%x4, ASI_BLK_XOR1, %x4	/*  IEU1				*/
+	wr		%x4, %x5, %asi		/*  LSU		Group+4bubbles		*/
+#else
+	wr		%x4, ASI_BLK_XOR, %asi	/*  LSU		Group+4bubbles		*/
+#endif
X 	andcc		%x3, 7, %x3		/*  IEU1	Group			*/
-	add		%dst, 8, %dst		/*  IEU0	Group			*/
+	add		%dst, 8, %dst		/*  IEU0				*/
X 	bne,pn		%icc, 1f		/*  CTI					*/
X 	 fzero		%f10			/*  FPA					*/
X 	brz,a,pn	%len, 2f		/*  CTI+IEU1	Group			*/
X 	 std		%f6, [%dst - 8]		/*  Store				*/
-1:	rd		%asi, %x4		/*  LSU		Group+4bubbles		*/
-	sub		%src, 64, %src		/*  IEU0	Group			*/
-	cmp		%len, 8			/*  IEU1				*/
+1:	cmp		%len, 8			/*  IEU1				*/
X 	blu,pn		%icc, 3f		/*  CTI					*/
-	 wr		%x4, ASI_BLK_XOR, %asi	/*  LSU		Group+4bubbles		*/
+	 sub		%src, 64, %src		/*  IEU0	Group			*/
X 1:	ldda		[%src] %asi, %f2	/*  Load	Group			*/
X 	fpadd32		%f10, %f2, %f12		/*  FPA		Group+load stall	*/
X 	add		%src, 8, %src		/*  IEU0				*/
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/VISmemset.S linux/arch/sparc64/lib/VISmemset.S
--- v2.3.3/linux/arch/sparc64/lib/VISmemset.S	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/lib/VISmemset.S	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: VISmemset.S,v 1.8 1998/06/12 14:53:59 jj Exp $
+/* $Id: VISmemset.S,v 1.9 1999/05/25 16:53:01 jj Exp $
X  * VISmemset.S: High speed memset operations utilizing the UltraSparc
X  *        Visual Instruction Set.
X  *
@@ -143,7 +143,8 @@
X 	VISEntryHalf
X #endif
X 	ldd		[%o0 - 8], %f0
-18:	wr		%g0, ASI_BLK_P, %asi
+18:	rd		%asi, %g2
+	wr		%g0, ASI_BLK_P, %asi
X 	membar		#StoreStore | #LoadStore
X 	andcc		%o3, 0xc0, %g5
X 	and		%o2, 0x3f, %o2
@@ -174,6 +175,7 @@
X 	 add		%o0, 256, %o0
X 12:
X #ifdef __KERNEL__
+	wr		%g2, %g0, %asi
X 	VISExitHalf
X #else
X #ifndef REGS_64BIT
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S
--- v2.3.3/linux/arch/sparc64/lib/blockops.S	Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc64/lib/blockops.S	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.16 1998/10/20 03:09:04 jj Exp $
+/* $Id: blockops.S,v 1.17 1999/05/25 16:52:52 jj Exp $
X  * blockops.S: UltraSparc block zero optimized routines.
X  *
X  * Copyright (C) 1996,1998 David S. Miller (da...@caip.rutgers.edu)
@@ -136,6 +136,7 @@
X 
X 	faddd		%f0, %f2, %f12			! FPA	Group
X 	fmuld		%f0, %f2, %f14			! FPM
+	rd		%asi, %g2			! LSU	Group
X 	wr		%g0, ASI_BLK_P, %asi		! LSU	Group
X 	membar		#StoreLoad | #StoreStore | #LoadStore	! LSU	Group
X 1:	stda		%f0, [%o0 + 0x00] %asi		! Store	Group
@@ -147,6 +148,7 @@
X 	bne,pt		%icc, 1b			! CTI
X 	 add		%o0, 0x100, %o0			! IEU0	Group
X 	membar		#Sync				! LSU	Group
+	wr		%g2, %g0, %asi			! LSU	Group
X 	VISExitHalf
X 
X 	stxa		%g5, [%o2] ASI_DMMU
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S
--- v2.3.3/linux/arch/sparc64/lib/checksum.S	Sun Oct  4 10:22:43 1998
+++ linux/arch/sparc64/lib/checksum.S	Thu May 27 09:55:21 1999
@@ -18,6 +18,7 @@
X #include <asm/ptrace.h>
X #include <asm/asi.h>
X #include <asm/page.h>
+#include <asm/asm_offsets.h>
X 
X 	/* The problem with the "add with carry" instructions on Ultra
X 	 * are two fold.  Firstly, they cannot pair with jack shit,
@@ -265,10 +266,12 @@
X 	.globl	cpc_handler
X cpc_handler:
X 	ldx	[%sp + 0x7ff + 128], %g1
+	ldub	[%g6 + AOFF_task_tss + AOFF_thread_current_ds], %g3
X 	sub	%g0, EFAULT, %g2
X 	brnz,a,pt %g1, 1f
X 	 st	%g2, [%g1]
X 1:	sethi	%uhi(PAGE_OFFSET), %g4
+	wr	%g3, %g0, %asi
X 	retl
X 	 sllx	%g4, 32, %g4
X 
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/strlen_user.S linux/arch/sparc64/lib/strlen_user.S
--- v2.3.3/linux/arch/sparc64/lib/strlen_user.S	Thu Sep  4 12:54:48 1997
+++ linux/arch/sparc64/lib/strlen_user.S	Thu May 27 09:55:21 1999
@@ -20,26 +20,26 @@
X 	andcc	%o0, 3, %g0
X 	be,pt	%icc, 9f
X 	 sethi	%hi(HI_MAGIC), %o4
-10:	lduba	[%o0] ASI_S, %o5
+10:	lduba	[%o0] %asi, %o5
X 	brz,pn	%o5, 21f
X 	 add	%o0, 1, %o0
X 	andcc	%o0, 3, %g0
X 	be,pn	%icc, 4f
X 	 or	%o4, %lo(HI_MAGIC), %o3
-11:	lduba	[%o0] ASI_S, %o5
+11:	lduba	[%o0] %asi, %o5
X 	brz,pn	%o5, 22f
X 	 add	%o0, 1, %o0
X 	andcc	%o0, 3, %g0
X 	be,pt	%icc, 13f
X 	 srl	%o3, 7, %o2
-12:	lduba	[%o0] ASI_S, %o5
+12:	lduba	[%o0] %asi, %o5
X 	brz,pn	%o5, 23f
X 	 add	%o0, 1, %o0
X 	ba,pt	%icc, 2f
-15:	 lda	[%o0] ASI_S, %o5
+15:	 lda	[%o0] %asi, %o5
X 9:	or	%o4, %lo(HI_MAGIC), %o3
X 4:	srl	%o3, 7, %o2
-13:	lda	[%o0] ASI_S, %o5
+13:	lda	[%o0] %asi, %o5
X 2:	sub	%o5, %o2, %o4
X 	andcc	%o4, %o3, %g0
X 	be,pt	%icc, 13b
@@ -60,7 +60,7 @@
X 	 add	%o4, 1, %o4
X 	andcc	%o5, 0xff, %g0
X 	bne,a,pt %icc, 2b
-14:	 lda	[%o0] ASI_S, %o5
+14:	 lda	[%o0] %asi, %o5
X 	add	%o4, 1, %o4
X 1:	retl
X 	 sub	%o4, %o1, %o0
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/lib/strncpy_from_user.S linux/arch/sparc64/lib/strncpy_from_user.S
--- v2.3.3/linux/arch/sparc64/lib/strncpy_from_user.S	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/lib/strncpy_from_user.S	Thu May 27 09:55:21 1999
@@ -1,7 +1,7 @@
-/* $Id: strncpy_from_user.S,v 1.5 1997/09/08 11:29:23 jj Exp $
+/* $Id: strncpy_from_user.S,v 1.6 1999/05/25 16:53:05 jj Exp $
X  * strncpy_from_user.S: Sparc64 strncpy from userspace.
X  *
- *  Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ *  Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X  */
X 
X #include <asm/asi.h>
@@ -37,19 +37,20 @@
X 	andcc	%o1, 7, %g0		! IEU1
X 	bne,pn	%icc, 30f		! CTI
X 	 ldx	[%o5 + %lo(0b)], %o4	! Load	Group
-60:	ldxa	[%o1] ASI_S, %g1	! Load	Group
-	add	%o1, %o2, %o1		! IEU0
-	subcc	%g0, %o2, %o3		! IEU1
-	bgeu,pn	%xcc, 10f		! CTI
+	add	%o0, %o2, %g3		! IEU0
+60:	ldxa	[%o1] %asi, %g1		! Load	Group
+	brlez,pn %o2, 10f		! CTI
X 	 sllx	%o4, 7, %o5		! IEU0	Group
-	add	%o0, %o2, %o0		! IEU1
+	mov	%o0, %o3		! IEU1
X 1:	sub	%g1, %o4, %g2		! IEU0	Group
-	stx	%g1, [%o0 + %o3]	! Store
+	stx	%g1, [%o0]		! Store
+	add	%o0, 8, %o0		! IEU1
X 	andcc	%g2, %o5, %g0		! IEU1	Group
X 	bne,pn	%xcc, 5f		! CTI
-	 add	%o3, 8, %o3		! IEU0
-	brlz,a,pt %o3, 1b		! CTI(IEU1) Group
-61:	 ldxa	[%o1 + %o3] ASI_S, %g1	! Load
+	 add	%o1, 8, %o1		! IEU0
+	cmp	%o0, %g3		! IEU1	Group
+	bl,a,pt %xcc, 1b		! CTI
+61:	 ldxa	[%o1] %asi, %g1		! Load
X 10:	retl				! CTI	Group
X 	 mov	%o2, %o0		! IEU0
X 5:	srlx	%g2, 32, %g7		! IEU0	Group
@@ -78,44 +79,45 @@
X 	be,pn	%icc, 56f		! CTI
X 	 andcc	%g1, 0xff, %g0		! IEU1	Group
X 	be,a,pn	%icc, 57f		! CTI
-	 add	%o2, %o3, %o0		! IEU0
-2:	brlz,a,pt %o3, 1b		! CTI(IEU1) Group
-62:	 ldxa	[%o1 + %o3] ASI_S, %g1	! Load
+	 sub	%o0, %o3, %o0		! IEU0
+2:	cmp	%o0, %g3		! IEU1	Group
+	bl,a,pt	%xcc, 1b		! CTI
+62:	 ldxa	[%o1] %asi, %g1		! Load
X 	retl				! CTI	Group
X 	 mov	%o2, %o0		! IEU0
-50:	add	%o2, %o3, %o0
+50:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 8, %o0
-51:	add	%o2, %o3, %o0
+51:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 7, %o0
-52:	add	%o2, %o3, %o0
+52:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 6, %o0
-53:	add	%o2, %o3, %o0
+53:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 5, %o0
-54:	add	%o2, %o3, %o0
+54:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 4, %o0
-55:	add	%o2, %o3, %o0
+55:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 3, %o0
-56:	add	%o2, %o3, %o0
+56:	sub	%o0, %o3, %o0
X 	retl
X 	 sub	%o0, 2, %o0
X 57:	retl
X 	 sub	%o0, 1, %o0
X 30:	brlez,pn %o2, 3f
-	 add	%o1, %o2, %o1
-	sub	%g0, %o2, %o3
+	 sub	%g0, %o2, %o3
X 	add	%o0, %o2, %o0
-63:	lduba	[%o1 + %o3] ASI_S, %o4
-1:	brz,pn	%o4, 2f
+63:	lduba	[%o1] %asi, %o4
+1:	add	%o1, 1, %o1
+	brz,pn	%o4, 2f
X 	 stb	%o4, [%o0 + %o3]
X 	addcc	%o3, 1, %o3
X 	bne,pt	%xcc, 1b
-64:	 lduba	[%o1 + %o3] ASI_S, %o4
+64:	 lduba	[%o1] %asi, %o4
X 3:	retl
X 	 mov	%o2, %o0
X 2:	retl
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/Makefile linux/arch/sparc64/math-emu/Makefile
--- v2.3.3/linux/arch/sparc64/math-emu/Makefile	Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc64/math-emu/Makefile	Sat May 29 11:09:04 1999
@@ -11,7 +11,7 @@
X O_OBJS   := math.o fabsq.o faddq.o fdivq.o fdmulq.o fitoq.o 		\
X 		fmovq.o fmulq.o fnegq.o fqtoi.o fqtox.o fsubq.o		\
X 		fxtoq.o fdtoq.o fstoq.o fqtos.o fqtod.o fsqrtq.o	\
-		fcmpq.o fcmpeq.o udivmodti4.o				\
+		fcmpq.o fcmpeq.o					\
X 		fsqrts.o fsqrtd.o fadds.o faddd.o fsubs.o fsubd.o	\
X 		fmuls.o fmuld.o fdivs.o fdivd.o fsmuld.o		\
X 		fstoi.o fdtoi.o fstox.o fdtox.o fstod.o fdtos.o
diff -u --recursive --new-file v2.3.3/linux/arch/sparc64/math-emu/double.h linux/arch/sparc64/math-emu/double.h
--- v2.3.3/linux/arch/sparc64/math-emu/double.h	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/math-emu/double.h	Sat May 29 11:09:04 1999
@@ -1,6 +1,26 @@
-/*
- * Definitions for IEEE Double Precision
- */
+/* Software floating-point emulation.
+ Definitions for IEEE Double Precision
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (r...@cygnus.com),
+		  Jakub Jelinek (j...@ultra.linux.cz),
+		  David S. Miller (da...@redhat.com) and
+		  Peter Maydell (pmay...@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 07'
echo 'File patch-2.3.4 is continued in part 08'
echo 08 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 11 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 11; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X  */
X 
-#include <linux/config.h>	/* for CONFIG_BLK_DEV_IDEPCI */
X #include <linux/types.h>
X #include <linux/kernel.h>
X #include <linux/delay.h>
diff -u --recursive --new-file v2.3.3/linux/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c
--- v2.3.3/linux/drivers/block/pdc4030.c	Fri May 14 18:55:14 1999
+++ linux/drivers/block/pdc4030.c	Fri May 28 09:34:41 1999
@@ -1,5 +1,5 @@
X /*  -*- linux-c -*-
- *  linux/drivers/block/pdc4030.c	Version 0.10  Jan 25, 1999
+ *  linux/drivers/block/pdc4030.c	Version 0.11  May 17, 1999
X  *
X  *  Copyright (C) 1995-1999  Linus Torvalds & authors (see below)
X  */
@@ -33,27 +33,43 @@
X  *  Version 0.09	Obsolete - never released - did manual write request
X  *			splitting before max_sectors[major][minor] available.
X  *  Version 0.10	Updated for 2.1 series of kernels
+ *  Version 0.11	Updated for 2.3 series of kernels
+ *			Autodetection code added.
X  */
X 
X /*
X  * Once you've compiled it in, you'll have to also enable the interface
X  * setup routine from the kernel command line, as in 
X  *
- *	'linux ide0=dc4030'
+ *	'linux ide0=dc4030' or 'linux ide1=dc4030'
X  *
X  * It should now work as a second controller also ('ide1=dc4030') but only
- * if you DON'T have BIOS V4.44, which has a bug. If you have this and EPROM
- * programming facilities, I can tell you what to fix...
+ * if you DON'T have BIOS V4.44, which has a bug. If you have this version
+ * and EPROM programming facilities, you need to fix 4 bytes:
+ * 	2496:	81	81
+ *	2497:	3E	3E
+ *	2498:	22	98	*
+ *	2499:	06	05	*
+ *	249A:	F0	F0
+ *	249B:	01	01
+ *	...
+ *	24A7:	81	81
+ *	24A8:	3E	3E
+ *	24A9:	22	98	*
+ *	24AA:	06	05	*
+ *	24AB:	70	70
+ *	24AC:	01	01
X  *
X  * As of January 1999, Promise Technology Inc. have finally supplied me with
X  * some technical information which has shed a glimmer of light on some of the
X  * problems I was having, especially with writes. 
+ *
+ * There are still problems with the robustness and efficiency of this driver
+ * because I still don't understand what the card is doing with interrupts.
X  */
X 
-#define DEBUG_READ
-#define DEBUG_WRITE
-
-#undef REALLY_SLOW_IO		/* most systems can safely undef this */
+#undef DEBUG_READ
+#undef DEBUG_WRITE
X 
X #include <linux/types.h>
X #include <linux/kernel.h>
@@ -70,11 +86,6 @@
X 
X #include "pdc4030.h"
X 
-/* This is needed as the controller may not interrupt if the required data is
-available in the cache. We have to simulate an interrupt. Ugh! */
-
-extern void ide_intr(int, void *dev_id, struct pt_regs*);
-
X /*
X  * promise_selectproc() is invoked by ide.c
X  * in preparation for access to the specified drive.
@@ -119,21 +130,27 @@
X 		return 1; /* device returned failure */
X }
X 
-ide_hwif_t *hwif_required = NULL;
+/*
+ * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive
+ */
+int pdc4030_identify(ide_drive_t *drive)
+{
+	return pdc4030_cmd(drive, PROMISE_IDENTIFY);
+}
+
+int enable_promise_support = 0;
X 
-void setup_pdc4030 (ide_hwif_t *hwif)
+void __init init_pdc4030 (void)
X {
-    hwif_required = hwif;
+	enable_promise_support = 1;
X }
X 
X /*
-init_pdc4030: Test for presence of a Promise caching controller card.
-Returns: 0 if no Promise card present at this io_base
-	 1 if Promise card found
-*/
-int init_pdc4030 (void)
+ * setup_pdc4030()
+ * Completes the setup of a Promise DC4030 controller card, once found.
+ */
+int __init setup_pdc4030 (ide_hwif_t *hwif)
X {
-	ide_hwif_t *hwif = hwif_required;
X         ide_drive_t *drive;
X 	ide_hwif_t *hwif2;
X 	struct dc_ident ident;
@@ -186,11 +203,25 @@
X             default:   hwif->irq = 15; break;
X 	}
X 	printk("on IRQ %d\n",hwif->irq);
+
+	/*
+	 * Once found and identified, we set up the next hwif in the array
+	 * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq
+	 * and other settings as the main hwif. This gives us two "mated"
+	 * hwifs pointing to the Promise card.
+	 *
+	 * We also have to shift the default values for the remaining
+	 * interfaces "up by one" to make room for the second interface on the
+	 * same set of values.
+	 */
+
X 	hwif->chipset	= hwif2->chipset = ide_pdc4030;
X 	hwif->mate	= hwif2;
X 	hwif2->mate	= hwif;
X 	hwif2->channel	= 1;
X 	hwif->selectproc = hwif2->selectproc = &promise_selectproc;
+	hwif->serialized = hwif2->serialized = 1;
+
X /* Shift the remaining interfaces down by one */
X 	for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
X 		ide_hwif_t *h = &ide_hwifs[i];
@@ -220,6 +251,50 @@
X }
X 
X /*
+ * detect_pdc4030()
+ * Tests for the presence of a DC4030 Promise card on this interface
+ * Returns: 1 if found, 0 if not found
+ */
+int __init detect_pdc4030(ide_hwif_t *hwif)
+{
+	ide_drive_t *drive = &hwif->drives[0];
+
+	if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */
+		return 0;
+	}
+	OUT_BYTE(0xF3, IDE_SECTOR_REG);
+	OUT_BYTE(0x14, IDE_SELECT_REG);
+	OUT_BYTE(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG);
+	
+	ide_delay_50ms();
+
+	if (IN_BYTE(IDE_ERROR_REG) == 'P' &&
+	    IN_BYTE(IDE_NSECTOR_REG) == 'T' &&
+	    IN_BYTE(IDE_SECTOR_REG) == 'I') {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+void __init ide_probe_for_pdc4030(void)
+{
+	unsigned int	index;
+	ide_hwif_t	*hwif;
+
+	if (enable_promise_support == 0)
+		return;
+	for (index = 0; index < MAX_HWIFS; index++) {
+		hwif = &ide_hwifs[index];
+		if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) {
+			setup_pdc4030(hwif);
+		}
+	}
+}
+
+
+
+/*
X  * promise_read_intr() is the handler for disk read/multread interrupts
X  */
X static void promise_read_intr (ide_drive_t *drive)
@@ -297,6 +372,21 @@
X }
X 
X /*
+ * promise_finish_write()
+ * called at the end of all writes
+ */
+static void promise_finish_write(ide_drive_t *drive)
+{
+	struct request *rq = HWGROUP(drive)->rq;
+	int i;
+
+	for (i = rq->nr_sectors; i > 0; ) {
+		i -= rq->current_nr_sectors;
+		ide_end_request(1, HWGROUP(drive));
+	}
+}
+
+/*
X  * promise_write_intr()
X  * This interrupt is called after the particularly odd polling for completion
X  * of the write request, once all the data has been sent.
@@ -304,8 +394,6 @@
X static void promise_write_intr(ide_drive_t *drive)
X {
X 	byte stat;
-	int i;
-	struct request *rq;
X 
X 	if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
X 		ide_error(drive, "promise_write_intr", stat);
@@ -314,11 +402,7 @@
X #ifdef DEBUG_WRITE
X 	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
X #endif
-	rq = HWGROUP(drive)->rq;
-	for (i = rq->nr_sectors; i > 0;) {
-		i -= rq->current_nr_sectors;
-		ide_end_request(1, HWGROUP(drive));
-	}
+	promise_finish_write(drive);
X }
X 
X /*
@@ -336,10 +420,11 @@
X 		return;
X 	}
X 
+	ide_multwrite(drive, 4);
X #ifdef DEBUG_WRITE
-	printk(KERN_DEBUG "%s: Doing last 4 sectors\n", drive->name);
+	printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
+		drive->name, GET_STAT());
X #endif
-	ide_multwrite(drive, 4);
X 	ide_set_handler(drive, &promise_write_intr, WAIT_CMD);
X 	return;
X }
@@ -358,8 +443,8 @@
X 
X #ifdef DEBUG_WRITE
X 	printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "
-	       "buffer=0x%08lx\n", drive->name, rq->sector,
-	       rq->sector + rq->nr_sectors - 1, rq->buffer);
+	       "buffer=0x%08x\n", drive->name, rq->sector,
+	       rq->sector + rq->nr_sectors - 1, (unsigned int)rq->buffer);
X #endif
X 	if (rq->nr_sectors > 4) {
X 		ide_multwrite(drive, rq->nr_sectors - 4);
@@ -368,7 +453,11 @@
X 		return;
X 	} else {
X 		ide_multwrite(drive, rq->nr_sectors);
-		ide_set_handler(drive, &promise_write_intr, WAIT_CMD);
+#ifdef DEBUG_WRITE
+		printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
+			"status = %02x\n", drive->name, GET_STAT());
+#endif
+		promise_finish_write(drive);
X 	}
X }
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/block/via82c586.c linux/drivers/block/via82c586.c
--- v2.3.3/linux/drivers/block/via82c586.c	Fri May 14 18:55:15 1999
+++ linux/drivers/block/via82c586.c	Wed May 26 16:55:40 1999
@@ -41,6 +41,7 @@
X  *  and its threshold is set to 3/4.
X  */
X 
+#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/kernel.h>
X #include <linux/timer.h>
diff -u --recursive --new-file v2.3.3/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.3.3/linux/drivers/cdrom/sonycd535.c	Fri May 14 18:55:15 1999
+++ linux/drivers/cdrom/sonycd535.c	Wed May 26 09:31:44 1999
@@ -318,7 +318,7 @@
X cdu535_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
X 	disable_interrupts();
-	if (wait_queue_active(&cdu535_irq_wait))
+	if (waitqueue_active(&cdu535_irq_wait))
X 		wake_up(&cdu535_irq_wait);
X 	else
X 		printk(CDU535_MESSAGE_NAME
diff -u --recursive --new-file v2.3.3/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.3/linux/drivers/char/Config.in	Fri May  7 11:05:30 1999
+++ linux/drivers/char/Config.in	Sat May 22 15:02:48 1999
@@ -159,6 +159,7 @@
X   if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
X     hex '  ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
X   fi
+  dep_tristate 'IIC on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT
X fi
X 
X endmenu
diff -u --recursive --new-file v2.3.3/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.3/linux/drivers/char/Makefile	Fri May  7 11:05:30 1999
+++ linux/drivers/char/Makefile	Sat May 22 15:02:48 1999
@@ -330,6 +330,16 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_I2C_PARPORT),y)
+L_OBJS += i2c-parport.o
+L_I2C = y
+else
+  ifeq ($(CONFIG_I2C_PARPORT),m)
+    M_OBJS += i2c-parport.o
+    M_I2C = y
+  endif
+endif
+
X ifeq ($(CONFIG_VIDEO_BWQCAM),y)
X L_OBJS += bw-qcam.o
X else
diff -u --recursive --new-file v2.3.3/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.3/linux/drivers/char/bttv.c	Fri May 14 18:55:15 1999
+++ linux/drivers/char/bttv.c	Sun May 30 10:18:03 1999
@@ -543,6 +543,8 @@
X         { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
X         /* Pixelview PlayTV (bt878) */
X         { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},
+        /* "Leadtek WinView 601", */
+        { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}},
X };
X #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
X 
@@ -2036,6 +2038,41 @@
X 				I2CWrite(&(btv->i2c), I2C_TDA9850,
X 					TDA9850_CON3, con3, 1);
X 			}
+		   
+		       /* PT2254A programming Jon Tombs, j...@gte.esi.us.es */
+		        if (btv->type == BTTV_WINVIEW_601) { 
+			   int bits_out, loops, vol, data;
+
+			   /* 32 levels logarithmic */
+			   vol = 32 - ((v.volume>>11));
+			   /* units */
+                           bits_out = (PT2254_DBS_IN_2>>(vol%5));
+			   /* tens */
+                           bits_out |= (PT2254_DBS_IN_10>>(vol/5));
+			   bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL;
+			   data = btread(BT848_GPIO_DATA);
+			   data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
+				      WINVIEW_PT2254_STROBE);
+			   for (loops = 17; loops >= 0 ; loops--) {
+				if (bits_out & (1<<loops))
+				   data |=  WINVIEW_PT2254_DATA;
+				else
+				   data &= ~WINVIEW_PT2254_DATA;
+			       btwrite(data, BT848_GPIO_DATA);
+			       udelay(5);
+			       data |= WINVIEW_PT2254_CLK;
+			       btwrite(data, BT848_GPIO_DATA);
+			       udelay(5);
+			       data &= ~WINVIEW_PT2254_CLK;
+			       btwrite(data, BT848_GPIO_DATA);
+			   }
+			   data |=  WINVIEW_PT2254_STROBE;
+			   data &= ~WINVIEW_PT2254_DATA;
+			   btwrite(data, BT848_GPIO_DATA);
+			   udelay(10);			   
+			   data &= ~WINVIEW_PT2254_STROBE;
+			   btwrite(data, BT848_GPIO_DATA);
+			}
X 			if (btv->have_msp3400) 
X 			{
X                                 i2c_control_device(&(btv->i2c),
@@ -3033,6 +3070,9 @@
X 		case BTTV_VHX:
X 			strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)");
X  			break;
+	        case BTTV_WINVIEW_601:
+			strcpy(btv->video_dev.name,"BT848(Leadtek WinView 601)");
+ 			break;	   
X 	}
X 	printk("%s\n",btv->video_dev.name);
X 	audio(btv, AUDIO_MUTE);
diff -u --recursive --new-file v2.3.3/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.3.3/linux/drivers/char/bttv.h	Fri May 14 18:55:15 1999
+++ linux/drivers/char/bttv.h	Sun May 30 10:18:03 1999
@@ -210,6 +210,7 @@
X #define BTTV_VHX           0x0e
X #define BTTV_ZOLTRIX       0x0f
X #define BTTV_PIXVIEWPLAYTV 0x10
+#define BTTV_WINVIEW_601   0x11
X 
X #define AUDIO_TUNER        0x00
X #define AUDIO_RADIO        0x01
@@ -259,5 +260,13 @@
X #define TEA6300_TR         0x03		/* treble control */
X #define TEA6300_FA         0x04		/* fader control */
X #define TEA6300_SW         0x05		/* mute and source switch */
+
+#define PT2254_L_CHANEL 0x10
+#define PT2254_R_CHANEL 0x08
+#define PT2254_DBS_IN_2 0x400
+#define PT2254_DBS_IN_10 0x20000
+#define WINVIEW_PT2254_CLK  0x40
+#define WINVIEW_PT2254_DATA 0x20
+#define WINVIEW_PT2254_STROBE 0x80
X 
X #endif
diff -u --recursive --new-file v2.3.3/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.3.3/linux/drivers/char/cyclades.c	Mon May 17 09:55:21 1999
+++ linux/drivers/char/cyclades.c	Mon May 24 22:38:07 1999
@@ -1,7 +1,7 @@
X #define BLOCKMOVE
X #define	Z_WAKE
X static char rcsid[] =
-"$Revision: 2.2.2.1 $$Date: 1999/04/08 16:17:43 $";
+"$Revision: 2.2.2.2 $$Date: 1999/05/21 17:18:15 $";
X 
X /*
X  *  linux/drivers/char/cyclades.c
@@ -21,7 +21,7 @@
X  * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
X  * and then fixed as suggested by Michael K. Johnson 12/12/92.
X  *
- * This version does not support shared irq's.
+ * This version supports shared IRQ's (only for PCI boards).
X  *
X  * This module exports the following rs232 io functions:
X  *   int cy_init(void);
@@ -31,6 +31,17 @@
X  *   void cleanup_module(void);
X  *
X  * $Log: cyclades.c,v $
+ * Revision 2.2.2.2  1999/05/14 17:18:15 ivan
+ * /proc entry location changed to /proc/tty/driver/cyclades;
+ * Added support to shared IRQ's (only for PCI boards);
+ * Added support for Cobalt Qube2 systems;
+ * IRQ [de]allocation scheme revisited;
+ * BREAK implementation changed in order to make use of the 'break_ctl'
+ * TTY facility;
+ * Fixed typo in TTY structure field 'driver_name';
+ * Included a PCI bridge reset and EEPROM reload in the board 
+ * initialization code (for both Y and Z series).
+ *
X  * Revision 2.2.2.1  1999/04/08 16:17:43 ivan
X  * Fixed a bug in cy_wait_until_sent that was preventing the port to be 
X  * closed properly after a SIGINT;
@@ -536,7 +547,7 @@
X #undef	CY_16Y_HACK
X #undef	CY_ENABLE_MONITORING
X #undef	CY_PCI_DEBUG
-#define	CY_PROC
+#undef	CY_PROC
X 
X #if 0
X #define PAUSE __asm__("nop");
@@ -600,6 +611,14 @@
X #include <linux/stat.h>
X #include <linux/proc_fs.h>
X 
+#ifdef CONFIG_COBALT_27
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#define	CACHED_TO_UNCACHED(x)	(((unsigned long)(x) & \
+				  (unsigned long)0x1fffffff) + KSEG1)
+#endif
+
X #define cy_put_user	put_user
X 
X static unsigned long cy_get_user(unsigned long *addr)
@@ -638,6 +657,7 @@
X static struct tty_driver cy_serial_driver, cy_callout_driver;
X static int serial_refcount;
X 
+#ifndef CONFIG_COBALT_27
X static volatile int cy_irq_triggered;
X static volatile int cy_triggered;
X static int cy_wild_int_mask;
@@ -665,6 +685,8 @@
X };
X #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
X 
+#endif /* CONFIG_COBALT_27 */
+
X /* This is the per-card data structure containing address, irq, number of
X    channels, etc. This driver supports a maximum of NR_CARDS cards.
X */
@@ -681,11 +703,6 @@
X static struct termios *serial_termios[NR_PORTS];
X static struct termios *serial_termios_locked[NR_PORTS];
X 
-/* This is the per-irq data structure,
-   it maps an irq to the corresponding card */
-
-static struct cyclades_card     *IRQ_cards[NR_IRQS];
-
X /*
X  * tmp_buf is used as a temporary buffer by serial_write.  We need to
X  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -790,7 +807,9 @@
X 
X static void cy_start(struct tty_struct *);
X static void set_line_char(struct cyclades_port *);
+#ifndef CONFIG_COBALT_27
X static void cy_probe(int, void *, struct pt_regs *);
+#endif /* CONFIG_COBALT_27 */
X static void cyz_poll(unsigned long);
X #ifdef CYCLOM_SHOW_STATUS
X static void show_status(int);
@@ -959,6 +978,8 @@
X     return(0);
X } /* cyy_issue_cmd */
X 
+#ifndef CONFIG_COBALT_27	/* ISA interrupt detection code */
+
X static int probe_ready;
X 
X /*
@@ -1149,6 +1170,8 @@
X     return;
X } /* cy_probe */
X 
+#endif /* CONFIG_COBALT_27 */
+
X /* The real interrupt service routine is called
X    whenever the card wants its hand held--chars
X    received, out buffer empty, modem change, etc.
@@ -1172,9 +1195,9 @@
X   int mdm_change;
X   int mdm_status;
X 
-    if((cinfo = IRQ_cards[irq]) == 0){
+    if((cinfo = (struct cyclades_card *)dev_id) == 0){
X #ifdef CY_DEBUG_INTERRUPTS
-printk("cy_interrupt: spurious interrupt %d\n\r", irq);
+	printk("cy_interrupt: spurious interrupt %d\n\r", irq);
X #endif
X         return; /* spurious interrupt */
X     }
@@ -1206,7 +1229,7 @@
X                 }
X                 if (status & CySRReceive) { /* reception interrupt */
X #ifdef CY_DEBUG_INTERRUPTS
-printk("cy_interrupt: rcvd intr, chip %d\n\r", chip);
+		    printk("cy_interrupt: rcvd intr, chip %d\n\r", chip);
X #endif
X                     /* determine the channel & change to that context */
X                     save_xir = (u_char) cy_readb(base_addr+(CyRIR<<index));
@@ -1333,7 +1356,7 @@
X                        is empty, we know we can always stuff a dozen
X                        characters. */
X #ifdef CY_DEBUG_INTERRUPTS
-printk("cy_interrupt: xmit intr, chip %d\n\r", chip);
+		    printk("cy_interrupt: xmit intr, chip %d\n\r", chip);
X #endif
X 
X                     /* determine the channel & change to that context */
@@ -1368,37 +1391,19 @@
X                         info->x_char = 0;
X                     }
X 
-                    if (info->x_break){
-                        /*  The Cirrus chip requires the "Embedded
-			    Transmit Commands" of start break, delay,
-			    and end break sequences to be sent.  The
-			    duration of the break is given in TICs,
-			    which runs at HZ (typically 100) and the
-			    PPR runs at 200 Hz, so the delay is
-			    duration * 200/HZ, and thus a break can
-			    run from 1/100 sec to about 5/4 sec.
-			    For CD1400 J or later, replace the 200 Hz
-			    by 500 Hz.
-                         */
-			/* start break */
-                        cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-                        cy_writeb((u_long)base_addr + (CyTDR<<index), 0x81);
-			/* delay a bit */
-                        cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-                        cy_writeb((u_long)base_addr + (CyTDR<<index), 0x82);
-                        if (info->chip_rev >= CD1400_REV_J ) {
-			    /* It is a CD1400 rev. J or later */
-                            cy_writeb((u_long)base_addr + (CyTDR<<index), 
-				      info->x_break*500/HZ);
-			} else {
-                            cy_writeb((u_long)base_addr + (CyTDR<<index), 
-				      info->x_break*200/HZ);
+                    if (info->breakon || info->breakoff) {
+			if (info->breakon) {
+			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
+			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0x81);
+			    info->breakon = 0;
+                            char_count -= 2;
+			}
+			if (info->breakoff) {
+			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
+			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0x83);
+			    info->breakoff = 0;
+                            char_count -= 2;
X 			}
-			/* finish break */
-                        cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-                        cy_writeb((u_long)base_addr + (CyTDR<<index), 0x83);
-                        char_count -= 7;
-                        info->x_break = 0;
X                     }
X 
X                     while (char_count-- > 0){
@@ -1871,12 +1876,6 @@
X 		    info->last_active = jiffies;
X 		    info->jiffies[2] = jiffies;
X 		}
-		if (info->x_break){
-		    printk("cyc cyz_poll shouldn't see x_break\n");
-		    info->x_break = 0;
-		    info->last_active = jiffies;
-		    info->jiffies[2] = jiffies;
-		}
X #ifdef BLOCKMOVE
X 		while(0 < (small_count
X 		    = cy_min((tx_bufsize - tx_put),
@@ -1946,26 +1945,35 @@
X startup(struct cyclades_port * info)
X {
X   unsigned long flags;
+  int retval = 0;
X   unsigned char *base_addr;
X   int card,chip,channel,index;
+  unsigned long page;
+
+    page = get_free_page(GFP_KERNEL);
+    if (!page)
+	return -ENOMEM;
+
+    save_flags(flags); cli();
X 
X     if (info->flags & ASYNC_INITIALIZED){
-        return 0;
+	free_page(page);
+	goto errout;
X     }
X 
X     if (!info->type){
X         if (info->tty){
X             set_bit(TTY_IO_ERROR, &info->tty->flags);
X         }
-        return 0;
-    }
-    if (!info->xmit_buf){
-        info->xmit_buf = (unsigned char *) get_free_page (GFP_KERNEL);
-        if (!info->xmit_buf){
-            return -ENOMEM;
-        }
+	free_page(page);
+	goto errout;
X     }
X 
+    if (info->xmit_buf)
+	free_page(page);
+    else
+	info->xmit_buf = (unsigned char *) page;
+
X     set_line_char(info);
X 
X     card = info->card;
@@ -1982,39 +1990,40 @@
X 	     card, chip, channel, (long)base_addr);/**/
X #endif
X 
-	save_flags(flags); cli();
-	    cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
X 
-	    cy_writeb((ulong)base_addr+(CyRTPR<<index), (info->default_timeout
-				 ? info->default_timeout
-				 : 0x02)); /* 10ms rx timeout */
+	cy_writeb((ulong)base_addr+(CyRTPR<<index), (info->default_timeout
+		 ? info->default_timeout : 0x02)); /* 10ms rx timeout */
X 
-	    cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
+	cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
X 
-	    cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
-	    cy_writeb((ulong)base_addr+(CyMSVR1<<index), CyRTS);
-	    cy_writeb((ulong)base_addr+(CyMSVR2<<index), CyDTR);
+	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb((ulong)base_addr+(CyMSVR1<<index), CyRTS);
+	cy_writeb((ulong)base_addr+(CyMSVR2<<index), CyDTR);
X 
X #ifdef CY_DEBUG_DTR
-	    printk("cyc:startup raising DTR\n");
-	    printk("     status: 0x%x, 0x%x\n",
-		   cy_readb(base_addr+(CyMSVR1<<index)), 
-                   cy_readb(base_addr+(CyMSVR2<<index)));
+	printk("cyc:startup raising DTR\n");
+	printk("     status: 0x%x, 0x%x\n",
+		cy_readb(base_addr+(CyMSVR1<<index)), 
+                cy_readb(base_addr+(CyMSVR2<<index)));
X #endif
X 
-	    cy_writeb((u_long)base_addr+(CySRER<<index),
-               cy_readb(base_addr+(CySRER<<index)) | CyRxData);
-	    info->flags |= ASYNC_INITIALIZED;
+	cy_writeb((u_long)base_addr+(CySRER<<index),
+		cy_readb(base_addr+(CySRER<<index)) | CyRxData);
+	info->flags |= ASYNC_INITIALIZED;
+
+	if (info->tty){
+	    clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	}
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	info->breakon = info->breakoff = 0;
+	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+	info->idle_stats.in_use    =
+	info->idle_stats.recv_idle =
+	info->idle_stats.xmit_idle = jiffies;
X 
-	    if (info->tty){
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	    }
-	    info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	    memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-	    info->idle_stats.in_use    =
-	    info->idle_stats.recv_idle =
-	    info->idle_stats.xmit_idle = jiffies;
X 	restore_flags(flags);
+
X     } else {
X       struct FIRM_ID *firm_id;
X       struct ZFW_CTRL *zfw_ctrl;
@@ -2022,6 +2031,8 @@
X       struct CH_CTRL *ch_ctrl;
X       int retval;
X 
+	restore_flags(flags);
+
X 	base_addr = (unsigned char*) (cy_card[card].base_addr);
X 
X         firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
@@ -2074,7 +2085,7 @@
X 	    clear_bit(TTY_IO_ERROR, &info->tty->flags);
X 	}
X 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
+	info->breakon = info->breakoff = 0;
X 	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
X 	info->idle_stats.in_use    =
X 	info->idle_stats.recv_idle =
@@ -2085,6 +2096,10 @@
X 	printk(" cyc startup done\n");
X #endif
X 	return 0;
+
+errout:
+	restore_flags(flags);
+	return retval;
X } /* startup */
X 
X 
@@ -3763,36 +3778,62 @@
X     return 0;
X } /* set_modem_info */
X 
+/*
+ * cy_break() --- routine which turns the break handling on or off
+ */
X static void
-send_break( struct cyclades_port * info, int duration)
+cy_break(struct tty_struct *tty, int break_state)
X {
+    struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
+    unsigned long flags;
+
+    if (serial_paranoia_check(info, tty->device, "cy_break"))
+	return;
X 
+    save_flags(flags); cli();
X     if (!IS_CYC_Z(cy_card[info->card])) {
X         /* Let the transmit ISR take care of this (since it
X 	   requires stuffing characters into the output stream).
X         */
-	info->x_break = duration;
-	if (!info->xmit_cnt ) {
-	    start_xmit(info);
+	if (break_state == -1) {
+	    if (!info->breakon) {
+		info->breakon = 1;
+		if (!info->xmit_cnt ) {
+		    start_xmit(info);
+		}
+	    }
+	} else {
+	    if (!info->breakoff) {
+		info->breakoff = 1;
+		if (!info->xmit_cnt ) {
+		    start_xmit(info);
+		}
+	    }
X 	}
X     } else {
-	/* For the moment we ignore the duration parameter!!!
-	   A better implementation will use C_CM_SET_BREAK
-	   and C_CM_CLR_BREAK with the appropriate delay.
-	 */
-#if 1
-// this appears to wedge the output data stream
-int retval;
-        retval = cyz_issue_cmd(&cy_card[info->card],
+	int retval;
+
+	if (break_state == -1) {
+	    retval = cyz_issue_cmd(&cy_card[info->card],
X 		(info->line) - (cy_card[info->card].first_line),
-		C_CM_SENDBRK, 0L);
-	if (retval != 0){
-	    printk("cyc:send_break retval at %d was %x\n",
-	        __LINE__, retval);
+		C_CM_SET_BREAK, 0L);
+	    if (retval != 0) {
+		printk("cyc:cy_break (set) retval at %d was %x\n",
+		        __LINE__, retval);
+	    }
+	} else {
+	    retval = cyz_issue_cmd(&cy_card[info->card],
+		(info->line) - (cy_card[info->card].first_line),
+		C_CM_CLR_BREAK, 0L);
+	    if (retval != 0) {
+		printk("cyc:cy_break (clr) retval at %d was %x\n",
+		        __LINE__, retval);
+	    }
X 	}
-#endif
X     }
-} /* send_break */
+    restore_flags(flags);
+
+} /* cy_break */
X 
X static int
X get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
@@ -4026,21 +4067,6 @@
X 	case CYGETWAIT:
X 	    ret_val = info->closing_wait / (HZ/100);
X 	    break;
-	case TCSBRK:    /* SVID version: non-zero arg --> no break */
-	    ret_val = tty_check_change(tty);
-	    if (ret_val)
-		return ret_val;
-	    tty_wait_until_sent(tty,0);
-	    if (!arg)
-		send_break(info, HZ/4); /* 1/4 second */
-	    break;
-	case TCSBRKP:   /* support for POSIX tcsendbreak() */
-	    ret_val = tty_check_change(tty);
-	    if (ret_val)
-		return ret_val;
-	    tty_wait_until_sent(tty,0);
-	    send_break(info, arg ? arg*(HZ/10) : HZ/4);
-	    break;
X         case TIOCMGET:
X             ret_val = get_modem_info(info, (unsigned int *) arg);
X             break;
@@ -4091,7 +4117,13 @@
X             tty->stopped = 0;
X             cy_start(tty);
X     }
-#ifdef tytso_patch_94Nov25_1726
+#if 0
+    /*
+     * No need to wake up processes in open wait, since they
+     * sample the CLOCAL flag once, and don't recheck it.
+     * XXX  It's not clear whether the current behavior is correct
+     * or not.  Hence, this may change.....
+     */
X     if (!(old_termios->c_cflag & CLOCAL) &&
X         (tty->termios->c_cflag & CLOCAL))
X             wake_up_interruptible(&info->open_wait);
@@ -4100,16 +4132,6 @@
X     return;
X } /* cy_set_termios */
X 
-
-/*
- * void (*set_ldisc)(struct tty_struct *tty);
- *
- * 	This routine allows the tty driver to be notified when the
- * 	device's termios settings have changed.
- * 
- */
-
-
X /* This routine is called by the upper-layer tty layer to signal
X    that incoming characters should be throttled because the input
X    buffers are close to full.
@@ -4467,6 +4489,7 @@
X     return chip_number;
X } /* cyy_init_card */
X 
+#ifndef CONFIG_COBALT_27
X /*
X  * ---------------------------------------------------------------------
X  * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
@@ -4530,7 +4553,7 @@
X 
X                 /* allocate IRQ */
X                 if(request_irq(cy_isa_irq, cyy_interrupt,
-				   SA_INTERRUPT, "cyclomY", NULL))
+				   SA_INTERRUPT, "Cyclom-Y", &cy_card[j]))
X                 {
X                         printk("Cyclom-Y/ISA found at 0x%lx ",
X                                 (unsigned long) cy_isa_address);
@@ -4546,7 +4569,6 @@
X                 cy_card[j].bus_index = 0;
X                 cy_card[j].first_line = cy_next_channel;
X                 cy_card[j].num_chips = cy_isa_nchan/4;
-                IRQ_cards[cy_isa_irq] = &cy_card[j];
X                 nboard++;
X                         
X                 /* print message */
@@ -4561,6 +4583,20 @@
X         return(nboard);
X 
X } /* cy_detect_isa */
+#endif /* CONFIG_COBALT_27 */
+
+static void plx_init(uclong addr, uclong initctl)
+{
+    /* Reset PLX */
+    cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
+    udelay(100L);
+    cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
+
+    /* Reload Config. Registers from EEPROM */
+    cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
+    udelay(100L);
+    cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
+}
X 
X /*
X  * ---------------------------------------------------------------------
@@ -4621,6 +4657,12 @@
X 		cy_pci_addr0  &= PCI_BASE_ADDRESS_MEM_MASK;
X 		cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
X 
+		if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) {
+		    printk("  Warning: PCI I/O bit incorrectly set. "
+			   "Ignoring it...\n");
+		    cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
+		}
+
X #if defined(__alpha__)
X                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
X 		    printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
@@ -4673,7 +4715,7 @@
X 
X                 /* allocate IRQ */
X                 if(request_irq(cy_pci_irq, cyy_interrupt,
-		        SA_INTERRUPT, "cyclomY", NULL))
+		        SA_SHIRQ, "Cyclom-Y", &cy_card[j]))
X                 {
X                         printk("Cyclom-Y/PCI found at 0x%lx ",
X 			    (ulong) cy_pci_addr2);
@@ -4689,13 +4731,14 @@
X                 cy_card[j].bus_index = 1;
X                 cy_card[j].first_line = cy_next_channel;
X                 cy_card[j].num_chips = cy_pci_nchan/4;
-                IRQ_cards[cy_pci_irq] = &cy_card[j];
X 
X                 /* enable interrupts in the PCI interface */
X 		plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
X 		switch (plx_ver) {
X 		    case PLX_9050:
X 
+		    plx_init(cy_pci_addr0, 0x50);
+
X 		    cy_writew(cy_pci_addr0+0x4c, 
X 			cy_readw(cy_pci_addr0+0x4c)|0x0040);
X 		    break;
@@ -4704,6 +4747,8 @@
X 		    case PLX_9080:
X 		    default: /* Old boards, use PLX_9060 */
X 
+		    plx_init(cy_pci_addr0, 0x6c);
+
X 		    cy_writew(cy_pci_addr0+0x68, 
X 			cy_readw(cy_pci_addr0+0x68)|0x0900);
X 		    break;
@@ -4742,9 +4787,18 @@
X #if !defined(__alpha__)
X                 cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl);
X #endif
+
+		plx_init(cy_pci_addr0, 0x6c);
+
X 		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
X 			   cy_pci_addr0)->mail_box_0);
X                 cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+		if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) {
+		    printk("  Warning: PCI I/O bit incorrectly set. "
+			   "Ignoring it...\n");
+		    cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
+		}
X 		if (mailbox == ZE_V1) {
X #if !defined(__alpha__)
X                	    cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ze_win);
@@ -4821,7 +4875,7 @@
X                 /* allocate IRQ only if board has an IRQ */
X 		if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) {
X 		    if(request_irq(cy_pci_irq,cyz_interrupt,
-			SA_INTERRUPT,"cyclomZ",NULL))
+			SA_SHIRQ,"Cyclades-Z",&cy_card[j]))
X 		    {
X 			printk("Could not allocate IRQ%d ",
X 			    cy_pci_irq);
@@ -4839,7 +4893,6 @@
X                 cy_card[j].bus_index = 1;
X                 cy_card[j].first_line = cy_next_channel;
X                 cy_card[j].num_chips = -1;
-                IRQ_cards[cy_pci_irq] = &cy_card[j];
X 
X                 /* print message */
X 		/* don't report IRQ if board is no IRQ */
@@ -4905,7 +4958,7 @@
X                 /* allocate IRQ only if board has an IRQ */
X 		if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) {
X 		    if(request_irq(cy_pci_irq,cyz_interrupt,
-			SA_INTERRUPT,"cyclomZ",NULL))
+			SA_SHIRQ,"Cyclades-Z",&cy_card[j]))
X 		    {
X 			printk("Could not allocate IRQ%d ",
X 			    cy_pci_irq);
@@ -4922,7 +4975,6 @@
X                 cy_card[j].bus_index = 1;
X                 cy_card[j].first_line = cy_next_channel;
X                 cy_card[j].num_chips = -1;
-                IRQ_cards[cy_pci_irq] = &cy_card[j];
X 
X                 /* print message */
X 		/* don't report IRQ if board is no IRQ */
@@ -4971,7 +5023,6 @@
X 	__DATE__, __TIME__);
X } /* show_version */
X 
-#ifdef CY_PROC
X static int 
X cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
X 		       int *eof, void *data)
@@ -5028,7 +5079,6 @@
X 	len = 0;
X     return len;
X }
-#endif
X 
X /* The serial driver boot-time initialization code!
X     Hardware I/O ports are mapped to character special devices on a
@@ -5062,13 +5112,15 @@
X   struct proc_dir_entry *ent;
X #endif
X 
+    init_bh(CYCLADES_BH, do_cyclades_bh);
+
X     show_version();
X 
X     /* Initialize the tty_driver structure */
X     
X     memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
X     cy_serial_driver.magic = TTY_DRIVER_MAGIC;
-    cy_serial_driver.name = "cyclades";
+    cy_serial_driver.driver_name = "cyclades";
X     cy_serial_driver.name = "ttyC";
X     cy_serial_driver.major = CYCLADES_MAJOR;
X     cy_serial_driver.minor_start = 0;
@@ -5083,6 +5135,7 @@
X     cy_serial_driver.table = serial_table;
X     cy_serial_driver.termios = serial_termios;
X     cy_serial_driver.termios_locked = serial_termios_locked;
+
X     cy_serial_driver.open = cy_open;
X     cy_serial_driver.close = cy_close;
X     cy_serial_driver.write = cy_write;
@@ -5098,7 +5151,9 @@
X     cy_serial_driver.stop = cy_stop;
X     cy_serial_driver.start = cy_start;
X     cy_serial_driver.hangup = cy_hangup;
+    cy_serial_driver.break_ctl = cy_break;
X     cy_serial_driver.wait_until_sent = cy_wait_until_sent;
+    cy_serial_driver.read_proc = cyclades_get_proc_info;
X 
X     /*
X      * The callout device is just like normal device except for
@@ -5117,12 +5172,6 @@
X     if (tty_register_driver(&cy_callout_driver))
X             panic("Couldn't register Cyclades callout driver\n");
X 
-    init_bh(CYCLADES_BH, do_cyclades_bh);
-
-    for (i = 0; i < NR_IRQS; i++) {
-            IRQ_cards[i] = 0;
-    }
-
X     for (i = 0; i < NR_CARDS; i++) {
X             /* base_addr=0 indicates board not found */
X             cy_card[i].base_addr = 0;
@@ -5135,9 +5184,11 @@
X        availability of cy_card and cy_port data structures and updating
X        the cy_next_channel. */
X 
+#ifndef CONFIG_COBALT_27
X     /* look for isa boards */
X     cy_isa_nboard = cy_detect_isa();
-    
+#endif /* CONFIG_COBALT_27 */
+
X     /* look for pci boards */
X     cy_pci_nboard = cy_detect_pci();
X 
@@ -5279,9 +5330,9 @@
X 		               cy_callout_driver.init_termios;
X                     info->normal_termios =
X 		               cy_serial_driver.init_termios;
-                    init_waitqueue(&info->open_wait);
-                    init_waitqueue(&info->close_wait);
-                    init_waitqueue(&info->shutdown_wait);
+                    init_waitqueue_head(&info->open_wait);
+                    init_waitqueue_head(&info->close_wait);
+                    init_waitqueue_head(&info->shutdown_wait);
X                     /* info->session */
X                     /* info->pgrp */
X                     info->read_status_mask =
@@ -5323,6 +5374,7 @@
X cleanup_module(void)
X {
X     int i;
+    int e1, e2;
X     unsigned long flags;
X 
X     if (cyz_timeron){
@@ -5333,11 +5385,12 @@
X     save_flags(flags); cli();
X     remove_bh(CYCLADES_BH);
X 
-    free_page((unsigned long)tmp_buf);
-    if (tty_unregister_driver(&cy_callout_driver))
-            printk("Couldn't unregister Cyclades callout driver\n");
-    if (tty_unregister_driver(&cy_serial_driver))
-            printk("Couldn't unregister Cyclades serial driver\n");
+    if ((e1 = tty_unregister_driver(&cy_serial_driver)))
+            printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
+		e1);
+    if ((e2 = tty_unregister_driver(&cy_callout_driver)))
+            printk("cyc: failed to unregister Cyclades callout driver (%d)\n", 
+		e2);
X 
X     restore_flags(flags);
X 
@@ -5345,9 +5398,13 @@
X         if (cy_card[i].base_addr != 0
X 	    && cy_card[i].irq)
X         {
-            free_irq(cy_card[i].irq,NULL);
+            free_irq(cy_card[i].irq, &cy_card[i]);
X         }
X     }
+    if (tmp_buf) {
+	free_page((unsigned long) tmp_buf);
+	tmp_buf = NULL;
+    }
X #ifdef CY_PROC
X     remove_proc_entry("cyclades", 0);
X #endif
@@ -5358,6 +5415,7 @@
X void
X cy_setup(char *str, int *ints)
X {
+#ifndef CONFIG_COBALT_27
X   int i, j;
X 
X     for (i = 0 ; i < NR_ISA_ADDRS ; i++) {
@@ -5368,6 +5426,7 @@
X             cy_isa_addresses[i++] = (unsigned char *)(ints[j]);
X         }
X     }
+#endif /* CONFIG_COBALT_27 */
X 
X } /* cy_setup */
X #endif
diff -u --recursive --new-file v2.3.3/linux/drivers/char/i2c-parport.c linux/drivers/char/i2c-parport.c
--- v2.3.3/linux/drivers/char/i2c-parport.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/i2c-parport.c	Sat May 22 15:02:48 1999
@@ -0,0 +1,149 @@
+/*
+ * I2C driver for parallel port
+ *
+ * Author: Phil Blundell <ph...@gnu.org>
+ *
+ * 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 driver implements a simple I2C protocol by bit-twiddling some
+ * signals on the parallel port.  Since the outputs on the parallel port
+ * aren't open collector, three lines rather than two are used:
+ *
+ *	D0	clock out
+ *	D1	data out
+ *	BUSY	data in	
+ */
+
+#include <linux/parport.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <asm/spinlock.h>
+
+#define I2C_DELAY   10
+
+static int debug = 0;
+
+struct parport_i2c_bus
+{
+  struct i2c_bus i2c;
+  struct parport_i2c_bus *next;
+};
+
+static struct parport_i2c_bus *bus_list;
+
+#ifdef __SMP__
+static spinlock_t bus_list_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
+/* software I2C functions */
+
+static void i2c_setlines(struct i2c_bus *bus, int clk, int data)
+{
+  struct parport *p = bus->data;
+  parport_write_data(p, (clk?1:0) | (data?2:0)); 
+  udelay(I2C_DELAY);
+}
+
+static int i2c_getdataline(struct i2c_bus *bus)
+{
+  struct parport *p = bus->data;
+  return (parport_read_status(p) & PARPORT_STATUS_BUSY) ? 0 : 1;
+}
+
+static struct i2c_bus parport_i2c_bus_template = 
+{
+  "...",
+  I2C_BUSID_PARPORT,
+  NULL,
+  
+  SPIN_LOCK_UNLOCKED,
+  
+  NULL,
+  NULL,
+	
+  i2c_setlines,
+  i2c_getdataline,
+  NULL,
+  NULL,
+};
+
+static void i2c_parport_attach(struct parport *port)
+{
+  struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus), 
+				      GFP_KERNEL);
+  b->i2c = parport_i2c_bus_template;
+  b->i2c.data = port;
+  strncpy(b->i2c.name, port->name, 32);
+  spin_lock(&bus_list_lock);
+  b->next = bus_list;
+  bus_list = b;
+  spin_unlock(&bus_list_lock);
+  i2c_register_bus(&b->i2c);
+  if (debug)
+    printk(KERN_DEBUG "i2c: attached to %s\n", port->name);
+}
+
+static void i2c_parport_detach(struct parport *port)
+{
+  struct parport_i2c_bus *b, *old_b = NULL;
+  spin_lock(&bus_list_lock);
+  b = bus_list;
+  while (b)
+  {
+    if (b->i2c.data == port)
+    {
+      if (old_b)
+	old_b->next = b->next;
+      else
+	bus_list = b->next;
+      i2c_unregister_bus(&b->i2c);
+      kfree(b);
+      break;
+    }
+    old_b = b;
+    b = b->next;
+  }
+  spin_unlock(&bus_list_lock);
+  if (debug)
+    printk(KERN_DEBUG "i2c: detached from %s\n", port->name);
+}
+
+static struct parport_driver parport_i2c_driver = 
+{
+  "i2c",
+  i2c_parport_attach,
+  i2c_parport_detach
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int __init i2c_parport_init(void)
+#endif
+{
+  printk("I2C: driver for parallel port v0.1 ph...@gnu.org\n");
+  parport_register_driver(&parport_i2c_driver);
+  return 0;
+}
+
+#ifdef MODULE
+MODULE_PARM(debug, "i");
+
+void cleanup_module(void)
+{
+  struct parport_i2c_bus *b = bus_list;
+  while (b)
+  {
+    struct parport_i2c_bus *next = b->next;
+    i2c_unregister_bus(&b->i2c);
+    kfree(b);
+    b = next;
+  }
+  parport_unregister_driver(&parport_i2c_driver);
+}
+#endif
diff -u --recursive --new-file v2.3.3/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.3/linux/drivers/char/keyboard.c	Mon May 17 09:55:21 1999
+++ linux/drivers/char/keyboard.c	Sat May 22 12:57:24 1999
@@ -247,9 +247,10 @@
X 		sysrq_pressed = !up_flag;
X 		return;
X 	} else if (sysrq_pressed) {
-		if (!up_flag)
+		if (!up_flag) {
X 			handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty);
-		return;
+			return;
+		}
X 	}
X #endif
X 
@@ -474,7 +475,6 @@
X 
X static void boot_it(void)
X {
-	if (kbd->slockstate & ~shift_state) return;
X 	ctrl_alt_del();
X }
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.3.3/linux/drivers/char/stallion.c	Fri Apr 16 08:20:23 1999
+++ linux/drivers/char/stallion.c	Wed May 26 09:31:45 1999
@@ -154,7 +154,7 @@
X  *	is already swapping a shared buffer won't make things any worse.
X  */
X static char			*stl_tmpwritebuf;
-static struct semaphore		stl_tmpwritesem = MUTEX;
+static DECLARE_MUTEX(stl_tmpwritesem);
X 
X /*
X  *	Define a local default termios struct. All ports will be created
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- v2.3.3/linux/drivers/isdn/Config.in	Mon Mar 15 16:11:29 1999
+++ linux/drivers/isdn/Config.in	Sun May 23 10:03:41 1999
@@ -19,34 +19,39 @@
X if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
X     bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
X     if [ "$CONFIG_HISAX_EURO" != "n" ]; then
-	    bool 'Support for german tarifinfo' CONFIG_DE_AOC
-	    bool 'Support for australian Microlink service (not for std. EURO)' CONFIG_HISAX_ML
+	    bool 'Support for german chargeinfo' CONFIG_DE_AOC
+	    bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+	    bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
X     fi
X     bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
X     bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
X     bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
X     bool 'HiSax Support for Teles 16.3c' CONFIG_HISAX_TELES3C 
+    bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
+    bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
X     bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+    bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+    bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
X     bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
X     bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
X     bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
X     bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
X     bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
-    bool 'HiSax Support for Sedlbauer speed card/win/star' CONFIG_HISAX_SEDLBAUER
+    bool 'HiSax Support for Sedlbauer speed card/win/star/fax' CONFIG_HISAX_SEDLBAUER
X     bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
X     bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
X     bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
X     bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
X     if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
X       if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-        bool 'HiSax Support for SPARC Am7930' CONFIG_HISAX_AMD7930
-        bool 'HiSax Support for SPARC DBRI' CONFIG_HISAX_DBRI
+        bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
X       fi
X     fi
X fi
X if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
X 	dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
X 	dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
+	dep_tristate 'Eicon.Diehl active card support (EXPERIMENTAL)' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
X fi
X dep_tristate 'AVM-B1 with CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
X if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/Makefile linux/drivers/isdn/Makefile
--- v2.3.3/linux/drivers/isdn/Makefile	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/Makefile	Sun May 23 10:03:41 1999
@@ -1,6 +1,6 @@
X SUB_DIRS     :=
X MOD_SUB_DIRS :=
-ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000
+ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon
X 
X L_OBJS :=
X LX_OBJS :=
@@ -33,6 +33,7 @@
X     OX_OBJS += isdn_common.o
X     ifdef CONFIG_ISDN_PPP
X       O_OBJS += isdn_ppp.o
+      M_OBJS += isdn_bsdcomp.o
X     endif
X     ifdef CONFIG_ISDN_X25
X       O_OBJS += isdn_x25iface.o
@@ -111,6 +112,16 @@
X else
X   ifeq ($(CONFIG_ISDN_DRV_ACT2000),m)
X     MOD_SUB_DIRS += act2000
+  endif
+endif
+
+ifeq ($(CONFIG_ISDN_DRV_EICON),y)
+  L_OBJS += eicon/eicon.o
+  SUB_DIRS += eicon
+  MOD_SUB_DIRS += eicon
+else
+  ifeq ($(CONFIG_ISDN_DRV_EICON),m)
+    MOD_SUB_DIRS += eicon
X   endif
X endif
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/act2000/act2000.h linux/drivers/isdn/act2000/act2000.h
--- v2.3.3/linux/drivers/isdn/act2000/act2000.h	Mon May 10 13:00:10 1999
+++ linux/drivers/isdn/act2000/act2000.h	Sun May 23 10:03:41 1999
@@ -1,8 +1,8 @@
-/* $Id: act2000.h,v 1.5 1997/10/09 22:22:59 fritz Exp $
+/* $Id: act2000.h,v 1.7 1999/04/12 13:13:54 fritz Exp $
X  *
X  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
X  *
- * Copyright 1997 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fr...@isdn4linux.de)
X  * Thanks to Friedemann Baitinger and IBM Germany
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,12 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: act2000.h,v $
+ * Revision 1.7  1999/04/12 13:13:54  fritz
+ * Made cards pointer static to avoid name-clash.
+ *
+ * Revision 1.6  1998/11/05 22:12:38  fritz
+ * Changed mail-address.
+ *
X  * Revision 1.5  1997/10/09 22:22:59  fritz
X  * New HL<->LL interface:
X  *   New BSENT callback with nr. of bytes included.
@@ -212,8 +218,6 @@
X         isdn_if interface;               /* Interface to upper layer         */
X         char regname[35];                /* Name used for request_region     */
X } act2000_card;
-
-extern act2000_card *actcards;
X 
X extern __inline__ void act2000_schedule_tx(act2000_card *card)
X {
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/act2000/act2000_isa.c linux/drivers/isdn/act2000/act2000_isa.c
--- v2.3.3/linux/drivers/isdn/act2000/act2000_isa.c	Thu Nov  5 09:58:43 1998
+++ linux/drivers/isdn/act2000/act2000_isa.c	Sun May 23 10:03:41 1999
@@ -1,8 +1,8 @@
-/* $Id: act2000_isa.c,v 1.5 1998/02/12 23:06:47 keil Exp $
+/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $
X  *
X  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
X  *
- * Copyright 1997 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fr...@isdn4linux.de)
X  * Thanks to Friedemann Baitinger and IBM Germany
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,17 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: act2000_isa.c,v $
+ * Revision 1.8  1999/01/05 18:29:25  he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.7  1998/11/05 22:12:41  fritz
+ * Changed mail-address.
+ *
+ * Revision 1.6  1998/06/17 19:51:09  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
X  * Revision 1.5  1998/02/12 23:06:47  keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/act2000/act2000_isa.h linux/drivers/isdn/act2000/act2000_isa.h
--- v2.3.3/linux/drivers/isdn/act2000/act2000_isa.h	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/act2000/act2000_isa.h	Sun May 23 10:03:41 1999
@@ -1,8 +1,8 @@
-/* $Id: act2000_isa.h,v 1.1 1997/09/23 18:00:07 fritz Exp $
+/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $
X  *
X  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
X  *
- * Copyright 1997 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fr...@isdn4linux.de)
X  * Thanks to Friedemann Baitinger and IBM Germany
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,9 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: act2000_isa.h,v $
+ * Revision 1.2  1998/11/05 22:12:43  fritz
+ * Changed mail-address.
+ *
X  * Revision 1.1  1997/09/23 18:00:07  fritz
X  * New driver for IBM Active 2000.
X  *
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/act2000/capi.c linux/drivers/isdn/act2000/capi.c
--- v2.3.3/linux/drivers/isdn/act2000/capi.c	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/act2000/capi.c	Sun May 23 10:03:41 1999
@@ -1,9 +1,9 @@
-/* $Id: capi.c,v 1.7 1998/02/23 23:35:41 fritz Exp $
+/* $Id: capi.c,v 1.8 1998/11/05 22:12:46 fritz Exp $
X  *
X  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
X  *        CAPI encoder/decoder
X  *
- * Copyright 1997 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fr...@isdn4linux.de)
X  * Thanks to Friedemann Baitinger and IBM Germany
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,9 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: capi.c,v $
+ * Revision 1.8  1998/11/05 22:12:46  fritz
+ * Changed mail-address.
+ *
X  * Revision 1.7  1998/02/23 23:35:41  fritz
X  * Eliminated some compiler warnings.
X  *
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/act2000/capi.h linux/drivers/isdn/act2000/capi.h
--- v2.3.3/linux/drivers/isdn/act2000/capi.h	Wed Apr  1 16:20:57 1998
+++ linux/drivers/isdn/act2000/capi.h	Sun May 23 10:03:41 1999
@@ -1,8 +1,8 @@
-/* $Id: capi.h,v 1.4 1997/10/01 09:21:04 fritz Exp $
+/* $Id: capi.h,v 1.5 1998/11/05 22:12:48 fritz Exp $
X  *
X  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
X  *
- * Copyright 1997 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fr...@isdn4linux.de)
X  * Thanks to Friedemann Baitinger and IBM Germany
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,9 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: capi.h,v $
+ * Revision 1.5  1998/11/05 22:12:48  fritz
+ * Changed mail-address.
+ *
X  * Revision 1.4  1997/10/01 09:21:04  fritz
X  * Removed old compatibility stuff for 2.0.X kernels.
X  * From now on, this code is for 2.1.X ONLY!
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/act2000/module.c linux/drivers/isdn/act2000/module.c
--- v2.3.3/linux/drivers/isdn/act2000/module.c	Mon May 10 13:00:10 1999
+++ linux/drivers/isdn/act2000/module.c	Sun May 23 10:03:41 1999
@@ -1,8 +1,8 @@
-/* $Id: module.c,v 1.7 1998/02/12 23:06:52 keil Exp $
+/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $
X  *
X  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
X  *
- * Copyright 1997 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fr...@isdn4linux.de)
X  * Thanks to Friedemann Baitinger and IBM Germany
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,12 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: module.c,v $
+ * Revision 1.9  1999/04/12 13:13:56  fritz
+ * Made cards pointer static to avoid name-clash.
+ *
+ * Revision 1.8  1998/11/05 22:12:51  fritz
+ * Changed mail-address.
+ *
X  * Revision 1.7  1998/02/12 23:06:52  keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -57,7 +63,7 @@
X };
X #define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short))
X 
-act2000_card *actcards = (act2000_card *) NULL;
+static act2000_card *cards = (act2000_card *) NULL;
X 
X /* Parameters to be set by insmod */
X static int   act_bus  =  0;
@@ -589,7 +595,7 @@
X static inline act2000_card *
X act2000_findcard(int driverid)
X {
-        act2000_card *p = actcards;
+        act2000_card *p = cards;
X 
X         while (p) {
X                 if (p->myid == driverid)
@@ -714,8 +720,8 @@
X         card->bus = bus;
X         card->port = port;
X         card->irq = irq;
-        card->next = actcards;
-        actcards = card;
+        card->next = cards;
+        cards = card;
X }
X 
X /*
@@ -805,9 +811,9 @@
X 				       bus);
X 		}
X 	}
-	if (!actcards)
+	if (!cards)
X 		return 1;
-        p = actcards;
+        p = cards;
X         while (p) {
X 		initialized = 0;
X 		if (!p->interface.statcallb) {
@@ -870,9 +876,9 @@
X                                 kfree(p);
X                                 p = q->next;
X                         } else {
-                                actcards = p->next;
+                                cards = p->next;
X                                 kfree(p);
-                                p = actcards;
+                                p = cards;
X                         }
X 			failed++;
X                 }
@@ -890,9 +896,9 @@
X act2000_init(void)
X {
X         printk(KERN_INFO "%s\n", DRIVERNAME);
-        if (!actcards)
+        if (!cards)
X 		act2000_addcard(act_bus, act_port, act_irq, act_id);
-        if (!actcards)
+        if (!cards)
X                 printk(KERN_INFO "act2000: No cards defined yet\n");
X         /* No symbols to export, hide all symbols */
X         EXPORT_NO_SYMBOLS;
@@ -903,14 +909,14 @@
X void
X cleanup_module(void)
X {
-        act2000_card *card = actcards;
+        act2000_card *card = cards;
X         act2000_card *last;
X         while (card) {
X                 unregister_card(card);
X 		del_timer(&card->ptimer);
X                 card = card->next;
X         }
-        card = actcards;
+        card = cards;
X         while (card) {
X                 last = card;
X                 card = card->next;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/avmb1/b1capi.c linux/drivers/isdn/avmb1/b1capi.c
--- v2.3.3/linux/drivers/isdn/avmb1/b1capi.c	Thu Nov  5 09:58:43 1998
+++ linux/drivers/isdn/avmb1/b1capi.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,49 @@
X /*
- * $Id: b1capi.c,v 1.10 1998/02/13 07:09:10 calle Exp $
+ * $Id: b1capi.c,v 1.14 1999/04/15 19:49:29 calle Exp $
X  * 
X  * CAPI 2.0 Module for AVM B1-card.
X  * 
X  * (c) Copyright 1997 by Carsten Paeth (ca...@calle.in-berlin.de)
X  * 
X  * $Log: b1capi.c,v $
+ * Revision 1.14  1999/04/15 19:49:29  calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.13  1999/01/05 18:29:31  he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.12  1998/10/25 14:38:58  fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.11  1998/03/29 16:05:58  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.4.2.18  1998/03/20 20:34:37  calle
+ * port valid check now only for T1, because of the PCI and PCMCIA cards.
+ *
+ * Revision 1.4.2.17  1998/03/20 14:38:17  calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.4.2.16  1998/03/20 09:01:08  calle
+ * Changes capi_register handling to get full support for 30 bchannels.
+ *
+ * Revision 1.4.2.15  1998/03/18 17:43:26  calle
+ * T1 with fastlink, bugfix for multicontroller support in capidrv.c
+ *
+ * Revision 1.4.2.14  1998/03/04 17:33:47  calle
+ * Changes for T1.
+ *
+ * Revision 1.4.2.13  1998/02/27 15:40:41  calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
+ * Revision 1.4.2.12  1998/02/24 17:58:25  calle
+ * changes for T1.
+ *
X  * Revision 1.10  1998/02/13 07:09:10  calle
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -76,7 +114,7 @@
X #include "capicmd.h"
X #include "capiutil.h"
X 
-static char *revision = "$Revision: 1.10 $";
+static char *revision = "$Revision: 1.14 $";
X 
X /* ------------------------------------------------------------- */
X 
@@ -84,7 +122,7 @@
X int loaddebug = 0;
X 
X MODULE_AUTHOR("Carsten Paeth <ca...@calle.in-berlin.de>");
-MODULE_PARM(showcapimsgs, "0-3i");
+MODULE_PARM(showcapimsgs, "0-5i");
X MODULE_PARM(loaddebug, "0-1i");
X 
X /* ------------------------------------------------------------- */
@@ -150,10 +188,11 @@
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 11'
echo 'File patch-2.3.4 is continued in part 12'
echo 12 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 18 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X }
X 
@@ -1038,15 +1010,14 @@
X 	isdn_ctrl ic;
X 
X 	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
+	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
+	if (chanp->debug & 1)
+		link_debug(chanp, 0, "STAT_DHUP");
+	lli_deliver_cause(chanp, &ic);
+	ic.driver = chanp->cs->myid;
+	ic.command = ISDN_STAT_DHUP;
+	ic.arg = chanp->chan;
+	chanp->cs->iif.statcallb(&ic);
X 	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);	/* DISCONN was sent from L3 */
X }
X 
@@ -1059,12 +1030,11 @@
X 	chanp->data_open = 0;
X 	FsmChangeState(fi, ST_NULL);
X 	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->lc_b->l2_establish = 0;	/* direct reset in lc_b->lcfi */
-		FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+		chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
X 	}
X 	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
X 		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
+			link_debug(chanp, 0, "STAT_BHUP");
X 		ic.driver = chanp->cs->myid;
X 		ic.command = ISDN_STAT_BHUP;
X 		ic.arg = chanp->chan;
@@ -1084,33 +1054,33 @@
X 		chanp->cs->iif.statcallb(&ic);
X 		chanp->Flags = 0;
X 	} else {
-		if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
-			if (chanp->debug & 1)
-				link_debug(chanp, "STAT_DHUP", 0);
-			if (chanp->cs->protocol == ISDN_PTYPE_EURO) {
-				chanp->proc->para.cause = 0x2f;
-				chanp->proc->para.loc = 0;
-			} else {
-				chanp->proc->para.cause = 0x70;
-				chanp->proc->para.loc = 0;
-			}
-			lli_deliver_cause(chanp);
-			ic.driver = chanp->cs->myid;
-			ic.command = ISDN_STAT_DHUP;
-			ic.arg = chanp->chan;
-			chanp->cs->iif.statcallb(&ic);
+		test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
+		if (chanp->debug & 1)
+			link_debug(chanp, 0, "STAT_DHUP");
+		if (chanp->cs->protocol == ISDN_PTYPE_EURO) {
+			chanp->proc->para.cause = 0x2f;
+			chanp->proc->para.loc = 0;
+		} else {
+			chanp->proc->para.cause = 0x70;
+			chanp->proc->para.loc = 0;
X 		}
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc);
+		lli_deliver_cause(chanp, &ic);
+		ic.driver = chanp->cs->myid;
+		ic.command = ISDN_STAT_DHUP;
+		ic.arg = chanp->chan;
+		chanp->cs->iif.statcallb(&ic);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc);
X 		chanp->Flags = 0;
-		FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
+		chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
X 	}
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
X }
X 
X /* *INDENT-OFF* */
X static struct FsmNode fnlist[] HISAX_INITDATA =
X {
X 	{ST_NULL,		EV_DIAL,		lli_prep_dialout},
+	{ST_NULL,		EV_RESUME,		lli_prep_dialout},
X 	{ST_NULL,		EV_SETUP_IND,		lli_deliver_call},
X 	{ST_NULL,		EV_SHUTDOWN_D,		lli_shutdown_d},
X 	{ST_NULL,		EV_DLRL,		lli_go_null},
@@ -1162,6 +1132,7 @@
X 	{ST_WAIT_BCONN,		EV_CINF,		lli_charge_info},
X 	{ST_ACTIVE,		EV_CINF,		lli_charge_info},
X 	{ST_ACTIVE,		EV_BC_REL,		lli_released_bchan},
+	{ST_ACTIVE,		EV_SUSPEND,		lli_suspend},
X 	{ST_ACTIVE,		EV_HANGUP,		lli_disconn_bchan},
X 	{ST_ACTIVE,		EV_DISCONNECT_IND,	lli_release_bchan},
X 	{ST_ACTIVE,		EV_RELEASE_CNF,		lli_received_d_relcnf},
@@ -1195,6 +1166,7 @@
X 	{ST_WAIT_DSHUTDOWN,	EV_DLRL,		lli_go_null},
X 	{ST_WAIT_DSHUTDOWN,	EV_DLEST,		lli_d_established},
X 	{ST_WAIT_DSHUTDOWN,	EV_DIAL,		lli_prep_dialout},
+	{ST_WAIT_DSHUTDOWN,	EV_RESUME,		lli_prep_dialout},
X 	{ST_WAIT_DSHUTDOWN,	EV_SETUP_IND,		lli_deliver_call},
X };
X /* *INDENT-ON* */
@@ -1202,153 +1174,6 @@
X 
X #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
X 
-static void
-lc_activate_l1(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 50);
-	FsmChangeState(fi, ST_LC_ACTIVATE_WAIT);
-	/* This timeout is to avoid a hang if no L1 activation is possible */
-	FsmAddTimer(&lf->act_timer, 30000, EV_LC_TIMER, NULL, 50);
-	lf->st->ma.manl1(lf->st, PH_ACTIVATE_REQ, NULL);
-}
-
-static void
-lc_activated_from_l1(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	if (lf->l2_establish)
-		FsmChangeState(fi, ST_LC_DELAY);
-	else {
-		FsmChangeState(fi, ST_LC_CONNECTED);
-		lf->lccall(lf, LC_ESTABLISH, NULL);
-	}
-}
-
-static void
-lc_l1_activated(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 50);
-	FsmChangeState(fi, ST_LC_DELAY);
-	/* This timer is needed for delay the first paket on a channel
-	   to be shure that the other side is ready too */
-	if (lf->delay)
-		FsmAddTimer(&lf->act_timer, lf->delay, EV_LC_TIMER, NULL, 51);
-	else
-		FsmEvent(fi, EV_LC_TIMER, NULL);
-}
-
-static void
-lc_start_l2(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-/*	if (!lf->st->l1.act_state)
-		lf->st->l1.act_state = 2;
-*/	if (lf->l2_establish) {
-		FsmChangeState(fi, ST_LC_ESTABLISH_WAIT);
-		if (lf->l2_start)
-			lf->st->ma.manl2(lf->st, DL_ESTABLISH, NULL);
-	} else {
-		FsmChangeState(fi, ST_LC_CONNECTED);
-		lf->lccall(lf, LC_ESTABLISH, NULL);
-	}
-}
-
-static void
-lc_connected(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 50);
-	FsmChangeState(fi, ST_LC_CONNECTED);
-	lf->lccall(lf, LC_ESTABLISH, NULL);
-}
-
-static void
-lc_release_l2(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	if (lf->l2_establish) {
-		FsmChangeState(fi, ST_LC_RELEASE_WAIT);
-		lf->st->ma.manl2(lf->st, DL_RELEASE, NULL);
-	} else {
-		FsmChangeState(fi, ST_LC_NULL);
-		lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL);
-		lf->lccall(lf, LC_RELEASE, NULL);
-	}
-}
-
-static void
-lc_l2_released(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmChangeState(fi, ST_LC_RELEASE_WAIT);
-	FsmDelTimer(&lf->act_timer, 51);
-	/* This delay is needed for send out the UA frame before
-	 * PH_DEACTIVATE the interface
-	 */
-	FsmAddTimer(&lf->act_timer, 20, EV_LC_TIMER, NULL, 54);
-}
-
-static void
-lc_release_l1(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 54);
-	FsmChangeState(fi, ST_LC_NULL);
-	lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL);
-	lf->lccall(lf, LC_RELEASE, NULL);
-}
-
-static void
-lc_l1_deactivated(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 54);
-	FsmChangeState(fi, ST_LC_NULL);
-	lf->lccall(lf, LC_RELEASE, NULL);
-}
-/* *INDENT-OFF* */
-static struct FsmNode LcFnList[] HISAX_INITDATA =
-{
-	{ST_LC_NULL,  		EV_LC_ESTABLISH,	lc_activate_l1},
-	{ST_LC_NULL,  		EV_LC_PH_ACTIVATE,	lc_activated_from_l1},
-	{ST_LC_NULL,  		EV_LC_DL_ESTABLISH,	lc_connected},
-	{ST_LC_ACTIVATE_WAIT,	EV_LC_PH_ACTIVATE,	lc_l1_activated},
-	{ST_LC_ACTIVATE_WAIT,	EV_LC_TIMER,		lc_release_l1},
-	{ST_LC_ACTIVATE_WAIT,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_DELAY,  		EV_LC_ESTABLISH,	lc_start_l2},
-	{ST_LC_DELAY,		EV_LC_TIMER,		lc_start_l2},
-	{ST_LC_DELAY,		EV_LC_DL_ESTABLISH,	lc_connected},
-	{ST_LC_DELAY,  		EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_ESTABLISH_WAIT,	EV_LC_DL_ESTABLISH,	lc_connected},
-	{ST_LC_ESTABLISH_WAIT,	EV_LC_RELEASE,		lc_release_l1},
-	{ST_LC_ESTABLISH_WAIT,	EV_LC_DL_RELEASE,	lc_release_l1},
-	{ST_LC_ESTABLISH_WAIT,  EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_CONNECTED,	EV_LC_ESTABLISH,	lc_connected},
-	{ST_LC_CONNECTED,	EV_LC_RELEASE,		lc_release_l2},
-	{ST_LC_CONNECTED,	EV_LC_DL_RELEASE,	lc_l2_released},
-	{ST_LC_CONNECTED,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_FLUSH_WAIT,	EV_LC_TIMER,		lc_release_l2},
-	{ST_LC_FLUSH_WAIT,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_RELEASE_WAIT,	EV_LC_DL_RELEASE,	lc_release_l1},
-	{ST_LC_RELEASE_WAIT,	EV_LC_TIMER,		lc_release_l1},
-	{ST_LC_FLUSH_WAIT,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-};
-/* *INDENT-ON* */
-
-
-#define LC_FN_COUNT (sizeof(LcFnList)/sizeof(struct FsmNode))
-
X HISAX_INITFUNC(void
X CallcNew(void))
X {
@@ -1357,18 +1182,11 @@
X 	callcfsm.strEvent = strEvent;
X 	callcfsm.strState = strState;
X 	FsmNew(&callcfsm, fnlist, FNCOUNT);
-
-	lcfsm.state_count = LC_STATE_COUNT;
-	lcfsm.event_count = LC_EVENT_COUNT;
-	lcfsm.strEvent = strLcEvent;
-	lcfsm.strState = strLcState;
-	FsmNew(&lcfsm, LcFnList, LC_FN_COUNT);
X }
X 
X void
X CallcFree(void)
X {
-	FsmFree(&lcfsm);
X 	FsmFree(&callcfsm);
X }
X 
@@ -1384,75 +1202,10 @@
X 			break;
X 		case (ISDN_PROTO_L2_HDLC):
X 		case (ISDN_PROTO_L2_TRANS):
+//		case (ISDN_PROTO_L2_MODEM):
X 			releasestack_transl2(st);
X 			break;
X 	}
-	/* Reset B-Channel Statemachine */
-	FsmDelTimer(&chanp->lc_b->act_timer, 79);
-	FsmChangeState(&chanp->lc_b->lcfi, ST_LC_NULL);
-}
-
-static void
-dc_l1man(struct PStack *st, int pr, void *arg)
-{
-	struct Channel *chanp;
-
-	chanp = (struct Channel *) st->lli.userdata;
-	switch (pr) {
-		case (PH_ACTIVATE_CNF):
-		case (PH_ACTIVATE_IND):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_ACTIVATE, NULL);
-			break;
-		case (PH_DEACTIVATE_IND):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_DEACTIVATE, NULL);
-			break;
-	}
-}
-
-static void
-dc_l2man(struct PStack *st, int pr, void *arg)
-{
-	struct Channel *chanp = (struct Channel *) st->lli.userdata;
-
-	switch (pr) {
-		case (DL_ESTABLISH):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_ESTABLISH, NULL);
-			break;
-		case (DL_RELEASE):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_RELEASE, NULL);
-			break;
-	}
-}
-
-static void
-bc_l1man(struct PStack *st, int pr, void *arg)
-{
-	struct Channel *chanp = (struct Channel *) st->lli.userdata;
-
-	switch (pr) {
-		case (PH_ACTIVATE_IND):
-		case (PH_ACTIVATE_CNF):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_ACTIVATE, NULL);
-			break;
-		case (PH_DEACTIVATE_IND):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_DEACTIVATE, NULL);
-			break;
-	}
-}
-
-static void
-bc_l2man(struct PStack *st, int pr, void *arg)
-{
-	struct Channel *chanp = (struct Channel *) st->lli.userdata;
-
-	switch (pr) {
-		case (DL_ESTABLISH):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL);
-			break;
-		case (DL_RELEASE):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_RELEASE, NULL);
-			break;
-	}
X }
X 
X struct Channel
@@ -1471,7 +1224,7 @@
X 			return (chanp);
X 		chanp++;
X 		i++;
-	}		
+	}
X 	return (NULL);
X }
X 
@@ -1491,62 +1244,85 @@
X 			return (1);
X 		chanp++;
X 		i++;
-	}		
+	}
X 	return (0);
X }
X 
X static void
-ll_handler(struct l3_process *pc, int pr, void *arg)
+dchan_l3l4(struct PStack *st, int pr, void *arg)
X {
+	struct l3_process *pc = arg;
+	struct IsdnCardState *cs = st->l1.hardware;
X 	struct Channel *chanp;
-	char tmp[64], tm[32];
+	int event;
+
+	switch (pr) {
+		case (DL_ESTABLISH | INDICATION):
+			event = EV_DLEST;
+			break;
+		case (DL_RELEASE | INDICATION):
+			event = EV_DLRL;
+			break;
+		default:
+			event = -1;
+			break;
+	}
+	if (event >= 0) {
+		int i;
X 
-	if (pr == CC_SETUP_IND) {
+		chanp = st->lli.userdata;
+		if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
+			i = 1;
+		else
+			i = 0;
+		while (i < 2) {
+			FsmEvent(&chanp->fi, event, NULL);
+			chanp++;
+			i++;
+		}
+		return;
+	} else if (pr == (CC_SETUP | INDICATION)) {
X 		if (!(chanp = selectfreechannel(pc->st))) {
-			pc->st->lli.l4l3(pc->st, CC_DLRL, pc);
-			return;
+			pc->st->lli.l4l3(pc->st, CC_DLRL | REQUEST, pc);
X 		} else {
X 			chanp->proc = pc;
X 			pc->chan = chanp;
X 			FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
-			return;
-		}
-	} else if (pr == CC_ESTABLISH) {
-		if (is_activ(pc->st)) {
-			pc->st->lli.l4l3(pc->st, CC_ESTABLISH, pc);
-			return;
-		} else if (!(chanp = selectfreechannel(pc->st))) {
-			pc->st->lli.l4l3(pc->st, CC_DLRL, pc);
-			return;
-		} else {
-			chanp->proc = pc;
-			FsmEvent(&chanp->fi, EV_ESTABLISH, NULL);
-			return;
X 		}
-
-			
+		return;
X 	}
-	chanp = pc->chan;
+	if (!(chanp = pc->chan))
+		return;
+
X 	switch (pr) {
-		case (CC_DISCONNECT_IND):
+		case (CC_DISCONNECT | INDICATION):
X 			FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL);
X 			break;
-		case (CC_RELEASE_CNF):
+		case (CC_RELEASE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+			break;
+		case (CC_SUSPEND | CONFIRM):
+			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+			break;
+		case (CC_RESUME | CONFIRM):
+			FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
+			break;
+		case (CC_RESUME_ERR):
X 			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
X 			break;
-		case (CC_RELEASE_IND):
+		case (CC_RELEASE | INDICATION):
X 			FsmEvent(&chanp->fi, EV_RELEASE_IND, NULL);
X 			break;
-		case (CC_SETUP_COMPLETE_IND):
+		case (CC_SETUP_COMPL | INDICATION):
X 			FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
X 			break;
-		case (CC_SETUP_CNF):
+		case (CC_SETUP | CONFIRM):
X 			FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
X 			break;
-		case (CC_INFO_CHARGE):
+		case (CC_CHARGE | INDICATION):
X 			FsmEvent(&chanp->fi, EV_CINF, NULL);
X 			break;
-		case (CC_NOSETUP_RSP_ERR):
+		case (CC_NOSETUP_RSP):
X 			FsmEvent(&chanp->fi, EV_NOSETUP_RSP, NULL);
X 			break;
X 		case (CC_SETUP_ERR):
@@ -1558,15 +1334,14 @@
X 		case (CC_RELEASE_ERR):
X 			FsmEvent(&chanp->fi, EV_RELEASE_ERR, NULL);
X 			break;
-		case (CC_PROCEEDING_IND):
-		case (CC_ALERTING_IND):
+		case (CC_PROCEEDING | INDICATION):
+		case (CC_ALERTING | INDICATION):
X 			break;
X 		default:
X 			if (chanp->debug & 0x800) {
-				jiftime(tm, jiffies);
-				sprintf(tmp, "%s Channel %d L3->L4 unknown primitiv %d\n",
-					tm, chanp->chan, pr);
-				HiSax_putstatus(chanp->cs, tmp);
+				HiSax_putstatus(chanp->cs, "Ch",
+					"%d L3->L4 unknown primitiv %x",
+					chanp->chan, pr);
X 			}
X 	}
X }
@@ -1576,7 +1351,7 @@
X {
X 	struct PStack *st = chanp->d_st;
X 	struct IsdnCardState *cs = chanp->cs;
-	char tmp[128];
+	char tmp[16];
X 
X 	HiSax_addlist(cs, st);
X 	setstack_HiSax(st, cs);
@@ -1590,95 +1365,50 @@
X 	st->l2.window = 1;
X 	st->l2.T200 = 1000;	/* 1000 milliseconds  */
X 	st->l2.N200 = 3;	/* try 3 times        */
-	if (st->protocol == ISDN_PTYPE_1TR6)
-		st->l2.T203 = 10000;	/* 10000 milliseconds */
+	st->l2.T203 = 10000;	/* 10000 milliseconds */
+	if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
+		sprintf(tmp, "DCh%d Q.921 ", chanp->chan);
X 	else
-		st->l2.T203 = 10000;	/* 5000 milliseconds  */
-	
-	sprintf(tmp, "Channel %d q.921", chanp->chan);
+		sprintf(tmp, "DCh Q.921 ");
X 	setstack_isdnl2(st, tmp);
-	setstack_isdnl3(st, chanp);
+	setstack_l3dc(st, chanp);
X 	st->lli.userdata = chanp;
X 	st->lli.l2writewakeup = NULL;
-	st->l3.l3l4 = ll_handler;
-	st->l1.l1man = dc_l1man;
-	st->l2.l2man = dc_l2man;
+	st->l3.l3l4 = dchan_l3l4;
X }
X 
X static void
-callc_debug(struct FsmInst *fi, char *s)
+callc_debug(struct FsmInst *fi, char *fmt, ...)
X {
-	char str[80], tm[32];
+	va_list args;
X 	struct Channel *chanp = fi->userdata;
+	char tmp[16];
X 
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Channel %d callc %s\n", tm, chanp->chan, s);
-	HiSax_putstatus(chanp->cs, str);
-}
-
-static void
-lc_debug(struct FsmInst *fi, char *s)
-{
-	char str[256], tm[32];
-	struct LcFsm *lf = fi->userdata;
-
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Channel %d dc %s\n", tm, lf->ch->chan, s);
-	HiSax_putstatus(lf->ch->cs, str);
-}
-
-static void
-dlc_debug(struct FsmInst *fi, char *s)
-{
-	char str[256], tm[32];
-	struct LcFsm *lf = fi->userdata;
-
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Channel %d bc %s\n", tm, lf->ch->chan, s);
-	HiSax_putstatus(lf->ch->cs, str);
+	va_start(args, fmt);
+	sprintf(tmp, "Ch%d callc ", chanp->chan);
+	VHiSax_putstatus(chanp->cs, tmp, fmt, args);
+	va_end(args);
X }
X 
X static void
-lccall_d(struct LcFsm *lf, int pr, void *arg)
-{
-	struct IsdnCardState *cs = lf->st->l1.hardware;
-	struct Channel *chanp;
-	int i;
-
-	if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) {
-		chanp = lf->ch;
-		i = 1;
-	} else {
-		chanp = cs->channel;
-		i = 0;
-	}
-	while (i < 2) {
-		switch (pr) {
-			case (LC_ESTABLISH):
-				FsmEvent(&chanp->fi, EV_DLEST, NULL);
-				break;
-			case (LC_RELEASE):
-				FsmEvent(&chanp->fi, EV_DLRL, NULL);
-				break;
-		}
-		chanp++;
-		i++;
-	}
+dummy_pstack(struct PStack *st, int pr, void *arg) {
+	printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);
X }
X 
X static void
-lccall_b(struct LcFsm *lf, int pr, void *arg)
-{
-	struct Channel *chanp = lf->ch;
-
-	switch (pr) {
-		case (LC_ESTABLISH):
-			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
-			break;
-		case (LC_RELEASE):
-			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
-			break;
-	}
+init_PStack(struct PStack **stp) {
+	*stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+	(*stp)->next = NULL;
+	(*stp)->l1.l1l2 = dummy_pstack;
+	(*stp)->l1.l1hw = dummy_pstack;
+	(*stp)->l1.l1tei = dummy_pstack;
+	(*stp)->l2.l2tei = dummy_pstack;
+	(*stp)->l2.l2l1 = dummy_pstack;
+	(*stp)->l2.l2l3 = dummy_pstack;
+	(*stp)->l3.l3l2 = dummy_pstack;
+	(*stp)->l3.l3l4 = dummy_pstack;
+	(*stp)->lli.l4l3 = dummy_pstack;
+	(*stp)->ma.layer = dummy_pstack;
X }
X 
X static void
@@ -1693,9 +1423,8 @@
X 	chanp->debug = 0;
X 	chanp->Flags = 0;
X 	chanp->leased = 0;
-	chanp->b_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
-	chanp->b_st->next = NULL;
-
+	init_PStack(&chanp->b_st);
+	chanp->b_st->l1.delay = DEFAULT_B_DELAY;
X 	chanp->fi.fsm = &callcfsm;
X 	chanp->fi.state = ST_NULL;
X 	chanp->fi.debug = 0;
@@ -1704,41 +1433,14 @@
X 	FsmInitTimer(&chanp->fi, &chanp->dial_timer);
X 	FsmInitTimer(&chanp->fi, &chanp->drel_timer);
X 	if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
-		chanp->d_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+		init_PStack(&chanp->d_st);
+		if (chan)
+			csta->channel->d_st->next = chanp->d_st;
X 		chanp->d_st->next = NULL;
X 		init_d_st(chanp);
-		chanp->lc_d = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC);
-		chanp->lc_d->lcfi.fsm = &lcfsm;
-		chanp->lc_d->lcfi.state = ST_LC_NULL;
-		chanp->lc_d->lcfi.debug = 0;
-		chanp->lc_d->lcfi.userdata = chanp->lc_d;
-		chanp->lc_d->lcfi.printdebug = lc_debug;
-		chanp->lc_d->type = LC_D;
-		chanp->lc_d->delay = 0;
-		chanp->lc_d->ch = chanp;
-		chanp->lc_d->st = chanp->d_st;
-		chanp->lc_d->l2_establish = !0;
-		chanp->lc_d->l2_start = !0;
-		chanp->lc_d->lccall = lccall_d;
-		FsmInitTimer(&chanp->lc_d->lcfi, &chanp->lc_d->act_timer);
X 	} else {
X 		chanp->d_st = csta->channel->d_st;
-		chanp->lc_d = csta->channel->lc_d;
X 	}
-	chanp->lc_b = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC);
-	chanp->lc_b->lcfi.fsm = &lcfsm;
-	chanp->lc_b->lcfi.state = ST_LC_NULL;
-	chanp->lc_b->lcfi.debug = 0;
-	chanp->lc_b->lcfi.userdata = chanp->lc_b;
-	chanp->lc_b->lcfi.printdebug = dlc_debug;
-	chanp->lc_b->type = LC_B;
-	chanp->lc_b->delay = DEFAULT_B_DELAY;
-	chanp->lc_b->ch = chanp;
-	chanp->lc_b->st = chanp->b_st;
-	chanp->lc_b->l2_establish = !0;
-	chanp->lc_b->l2_start = !0;
-	chanp->lc_b->lccall = lccall_b;
-	FsmInitTimer(&chanp->lc_b->lcfi, &chanp->lc_b->act_timer);
X 	chanp->data_open = 0;
X }
X 
@@ -1749,11 +1451,12 @@
X 	init_chan(0, csta);
X 	init_chan(1, csta);
X 	printk(KERN_INFO "HiSax: 2 channels added\n");
-#ifdef LAYER2_WATCHING
-	printk(KERN_INFO "LAYER2 ESTABLISH\n");
-	test_and_set_bit(FLG_START_D, &csta->channel->Flags);
-	FsmEvent(&csta->channel->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
-#endif
+	if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) {
+		printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
+		test_and_set_bit(FLG_START_D, &csta->channel->Flags);
+		csta->channel->d_st->lli.l4l3(csta->channel->d_st,
+			DL_ESTABLISH | REQUEST, NULL);
+	}
X 	return (2);
X }
X 
@@ -1779,8 +1482,6 @@
X 	for (i = 0; i < 2; i++) {
X 		FsmDelTimer(&csta->channel[i].drel_timer, 74);
X 		FsmDelTimer(&csta->channel[i].dial_timer, 75);
-		FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77);
-		FsmDelTimer(&csta->channel[i].lc_b->act_timer, 76);
X 		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
X 			release_d_st(csta->channel + i);
X 		if (csta->channel[i].b_st) {
@@ -1790,18 +1491,8 @@
X 			csta->channel[i].b_st = NULL;
X 		} else
X 			printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i);
-		if (csta->channel[i].lc_b) {
-			kfree(csta->channel[i].lc_b);
-			csta->channel[i].b_st = NULL;
-		}
X 		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
X 			release_d_st(csta->channel + i);
-			FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77);
-			if (csta->channel[i].lc_d) {
-				kfree(csta->channel[i].lc_d);
-				csta->channel[i].d_st = NULL;
-			} else
-				printk(KERN_WARNING "CallcFreeChan lc_d ch%d allready freed\n", i);
X 		} else
X 			csta->channel[i].d_st = NULL;
X 	}
@@ -1814,15 +1505,23 @@
X 	struct sk_buff *skb = arg;
X 
X 	switch (pr) {
-		case (DL_DATA):
+		case (DL_DATA  | INDICATION):
X 			if (chanp->data_open)
X 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
X 			else {
X 				dev_kfree_skb(skb);
X 			}
X 			break;
+		case (DL_ESTABLISH | INDICATION):
+		case (DL_ESTABLISH | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
+			break;
+		case (DL_RELEASE | INDICATION):
+		case (DL_RELEASE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
+			break;
X 		default:
-			printk(KERN_WARNING "lldata_handler unknown primitive %d\n",
+			printk(KERN_WARNING "lldata_handler unknown primitive %x\n",
X 			       pr);
X 			break;
X 	}
@@ -1835,22 +1534,24 @@
X 	struct sk_buff *skb = arg;
X 
X 	switch (pr) {
-		case (PH_DATA_IND):
+		case (PH_DATA | INDICATION):
X 			if (chanp->data_open)
X 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
X 			else {
-				if (chanp->lc_b->lcfi.state == ST_LC_DELAY)
-					FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL);
-				if (chanp->data_open) {
-					link_debug(chanp, "channel now open", 0);
-					chanp->cs->iif.rcvcallb_skb(chanp->cs->myid,
-						chanp->chan, skb);
-				} else
-					dev_kfree_skb(skb);
+				link_debug(chanp, 0, "channel not open");
+				dev_kfree_skb(skb);
X 			}
X 			break;
+		case (PH_ACTIVATE | INDICATION):
+		case (PH_ACTIVATE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
+			break;
+		case (PH_DEACTIVATE | INDICATION):
+		case (PH_DEACTIVATE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
+			break;
X 		default:
-			printk(KERN_WARNING "lltrans_handler unknown primitive %d\n",
+			printk(KERN_WARNING "lltrans_handler unknown primitive %x\n",
X 			       pr);
X 			break;
X 	}
@@ -1865,7 +1566,7 @@
X 	ic.driver = chanp->cs->myid;
X 	ic.command = ISDN_STAT_BSENT;
X 	ic.arg = chanp->chan;
-	ic.parm.length = len;
+//	ic.parm.length = len;
X 	chanp->cs->iif.statcallb(&ic);
X }
X 
@@ -1874,10 +1575,27 @@
X {
X 	struct PStack *st = chanp->b_st;
X 	struct IsdnCardState *cs = chanp->cs;
-	char tmp[128];
+	char tmp[16];
X 
X 	st->l1.hardware = cs;
-	chanp->bcs->mode = 2;
+	if (chanp->leased)
+		st->l1.bc = chanp->chan & 1;
+	else
+		st->l1.bc = chanp->proc->para.bchannel - 1;
+	switch (chanp->l2_active_protocol) {
+		case (ISDN_PROTO_L2_X75I):
+		case (ISDN_PROTO_L2_HDLC):
+			st->l1.mode = L1_MODE_HDLC;
+			break;
+		case (ISDN_PROTO_L2_TRANS):
+			st->l1.mode = L1_MODE_TRANS;
+			break;
+#if 0
+		case (ISDN_PROTO_L2_MODEM):
+			st->l1.mode = L1_MODE_MODEM;
+			break;
+#endif
+	}
X 	if (chanp->bcs->BC_SetStack(st, chanp->bcs))
X 		return (-1);
X 	st->l2.flag = 0;
@@ -1892,50 +1610,87 @@
X 	st->l3.debug = 0;
X 	switch (chanp->l2_active_protocol) {
X 		case (ISDN_PROTO_L2_X75I):
-			sprintf(tmp, "Channel %d x.75", chanp->chan);
+			sprintf(tmp, "Ch%d X.75", chanp->chan);
X 			setstack_isdnl2(st, tmp);
+			setstack_l3bc(st, chanp);
X 			st->l2.l2l3 = lldata_handler;
-			st->l1.l1man = bc_l1man;
-			st->l2.l2man = bc_l2man;
X 			st->lli.userdata = chanp;
X 			st->lli.l1writewakeup = NULL;
X 			st->lli.l2writewakeup = ll_writewakeup;
X 			st->l2.l2m.debug = chanp->debug & 16;
X 			st->l2.debug = chanp->debug & 64;
-			st->ma.manl2(st, MDL_NOTEIPROC, NULL);
-			st->l1.mode = L1_MODE_HDLC;
-			if (chanp->leased)
-				st->l1.bc = chanp->chan & 1;
-			else
-				st->l1.bc = chanp->proc->para.bchannel - 1;
X 			break;
X 		case (ISDN_PROTO_L2_HDLC):
-			st->l1.l1l2 = lltrans_handler;
-			st->l1.l1man = bc_l1man;
-			st->lli.userdata = chanp;
-			st->lli.l1writewakeup = ll_writewakeup;
-			st->l1.mode = L1_MODE_HDLC;
-			if (chanp->leased)
-				st->l1.bc = chanp->chan & 1;
-			else
-				st->l1.bc = chanp->proc->para.bchannel - 1;
-			break;
X 		case (ISDN_PROTO_L2_TRANS):
+//		case (ISDN_PROTO_L2_MODEM):
X 			st->l1.l1l2 = lltrans_handler;
-			st->l1.l1man = bc_l1man;
X 			st->lli.userdata = chanp;
X 			st->lli.l1writewakeup = ll_writewakeup;
-			st->l1.mode = L1_MODE_TRANS;
-			if (chanp->leased)
-				st->l1.bc = chanp->chan & 1;
-			else
-				st->l1.bc = chanp->proc->para.bchannel - 1;
+			setstack_transl2(st);
+			setstack_l3bc(st, chanp);
X 			break;
X 	}
X 	return (0);
X }
X 
X static void
+leased_l4l3(struct PStack *st, int pr, void *arg)
+{
+	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	struct sk_buff *skb = arg;
+
+	switch (pr) {
+		case (DL_DATA | REQUEST):
+			link_debug(chanp, 0, "leased line d-channel DATA");
+			dev_kfree_skb(skb);
+			break;
+		case (DL_ESTABLISH | REQUEST):
+			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
+			break;
+		case (DL_RELEASE | REQUEST):
+			break;
+		default:
+			printk(KERN_WARNING "transd_l4l3 unknown primitive %x\n",
+			       pr);
+			break;
+	}
+}
+
+static void
+leased_l1l2(struct PStack *st, int pr, void *arg)
+{
+	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	struct sk_buff *skb = arg;
+	int i,event = EV_DLRL;
+
+	switch (pr) {
+		case (PH_DATA | INDICATION):
+			link_debug(chanp, 0, "leased line d-channel DATA");
+			dev_kfree_skb(skb);
+			break;
+		case (PH_ACTIVATE | INDICATION):
+		case (PH_ACTIVATE | CONFIRM):
+			event = EV_DLEST;
+		case (PH_DEACTIVATE | INDICATION):
+		case (PH_DEACTIVATE | CONFIRM):
+			if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags))
+				i = 1;
+			else
+				i = 0;
+			while (i < 2) {
+				FsmEvent(&chanp->fi, event, NULL);
+				chanp++;
+				i++;
+			}
+			break;
+		default:
+			printk(KERN_WARNING
+				"transd_l1l2 unknown primitive %x\n", pr);
+			break;
+	}
+}
+
+static void
X channel_report(struct Channel *chanp)
X {
X }
@@ -1953,13 +1708,70 @@
X 		chanp[i].b_st->l2.l2m.debug = debugflags & 0x10;
X 		chanp[i].d_st->l2.debug = debugflags & 0x20;
X 		chanp[i].b_st->l2.debug = debugflags & 0x40;
-		chanp[i].lc_d->lcfi.debug = debugflags & 0x80;
-		chanp[i].lc_b->lcfi.debug = debugflags & 0x100;
+		chanp[i].d_st->l3.l3m.debug = debugflags & 0x80;
+		chanp[i].b_st->l3.l3m.debug = debugflags & 0x100;
X 		chanp[i].b_st->ma.tei_m.debug = debugflags & 0x200;
X 		chanp[i].b_st->ma.debug = debugflags & 0x200;
X 		chanp[i].d_st->l1.l1m.debug = debugflags & 0x1000;
+		chanp[i].b_st->l1.l1m.debug = debugflags & 0x2000;
+	}
+	if (debugflags & 4)
+		csta->debug |= DEB_DLOG_HEX;
+	else
+		csta->debug &= ~DEB_DLOG_HEX;
+}
+
+static char tmpbuf[256];
+
+static void
+capi_debug(struct Channel *chanp, capi_msg *cm)
+{
+	char *t = tmpbuf;
+
+	t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan);
+	t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length);
+	t--;
+	*t= 0;
+	HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
+}
+
+void
+lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
+	if ((cm->para[0] != 3) || (cm->para[1] != 0))
+		return;
+	if (cm->para[2]<3)
+		return;
+	if (cm->para[4] != 0)
+		return;
+	switch(cm->para[3]) {
+		case 4: /* Suspend */
+			if (cm->para[5]) {
+				strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+				FsmEvent(&chanp->fi, EV_SUSPEND, cm);
+			}
+			break;
+		case 5: /* Resume */
+			if (cm->para[5]) {
+				strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+				if (chanp->fi.state == ST_NULL) {
+					FsmEvent(&chanp->fi, EV_RESUME, cm);
+				} else {
+					FsmDelTimer(&chanp->dial_timer, 72);
+					FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73);
+				}
+			}
+			break;
+	}
+}
+
+void
+lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
+	if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
+		(cs->typ == ISDN_CTYPE_ELSA_PCI)) {
+		if (cs->hw.elsa.MFlag) {
+			cs->cardmsg(cs, CARD_AUX_IND, cm->para);
+		}
X 	}
-	csta->dlogflag = debugflags & 4;
X }
X 
X int
@@ -1967,9 +1779,9 @@
X {
X 	struct IsdnCardState *csta = hisax_findcard(ic->driver);
X 	struct Channel *chanp;
-	char tmp[128];
X 	int i;
-	unsigned int num;
+	u_int num;
+	u_long adr;
X 
X 	if (!csta) {
X 		printk(KERN_ERR
@@ -1977,32 +1789,32 @@
X 		       ic->command, ic->driver);
X 		return -ENODEV;
X 	}
+
X 	switch (ic->command) {
X 		case (ISDN_CMD_SETEAZ):
X 			chanp = csta->channel + ic->arg;
-			if (chanp->debug & 1) {
-				sprintf(tmp, "SETEAZ card %d %s", csta->cardnr + 1,
-					ic->parm.num);
-				link_debug(chanp, tmp, 1);
-			}
X 			break;
+
X 		case (ISDN_CMD_SETL2):
X 			chanp = csta->channel + (ic->arg & 0xff);
-			if (chanp->debug & 1) {
-				sprintf(tmp, "SETL2 card %d %ld", csta->cardnr + 1,
-					ic->arg >> 8);
-				link_debug(chanp, tmp, 1);
-			}
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "SETL2 card %d %ld",
+					csta->cardnr + 1, ic->arg >> 8);
X 			chanp->l2_protocol = ic->arg >> 8;
X 			break;
+		case (ISDN_CMD_SETL3):
+			chanp = csta->channel + (ic->arg & 0xff);
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "SETL3 card %d %ld",
+					csta->cardnr + 1, ic->arg >> 8);
+			chanp->l3_protocol = ic->arg >> 8;
+			break;
X 		case (ISDN_CMD_DIAL):
X 			chanp = csta->channel + (ic->arg & 0xff);
-			if (chanp->debug & 1) {
-				sprintf(tmp, "DIAL %s -> %s (%d,%d)",
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
X 					ic->parm.setup.eazmsn, ic->parm.setup.phone,
-				 ic->parm.setup.si1, ic->parm.setup.si2);
-				link_debug(chanp, tmp, 1);
-			}
+					ic->parm.setup.si1, ic->parm.setup.si2);
X 			chanp->setup = ic->parm.setup;
X 			if (!strcmp(chanp->setup.eazmsn, "0"))
X 				chanp->setup.eazmsn[0] = '\0';
@@ -2018,57 +1830,54 @@
X 		case (ISDN_CMD_ACCEPTB):
X 			chanp = csta->channel + ic->arg;
X 			if (chanp->debug & 1)
-				link_debug(chanp, "ACCEPTB", 1);
+				link_debug(chanp, 1, "ACCEPTB");
X 			FsmEvent(&chanp->fi, EV_ACCEPTB, NULL);
X 			break;
X 		case (ISDN_CMD_ACCEPTD):
X 			chanp = csta->channel + ic->arg;
X 			if (chanp->debug & 1)
-				link_debug(chanp, "ACCEPTD", 1);
+				link_debug(chanp, 1, "ACCEPTD");
X 			FsmEvent(&chanp->fi, EV_ACCEPTD, NULL);
X 			break;
X 		case (ISDN_CMD_HANGUP):
X 			chanp = csta->channel + ic->arg;
X 			if (chanp->debug & 1)
-				link_debug(chanp, "HANGUP", 1);
+				link_debug(chanp, 1, "HANGUP");
X 			FsmEvent(&chanp->fi, EV_HANGUP, NULL);
X 			break;
-		case (ISDN_CMD_SUSPEND):
-			chanp = csta->channel + ic->arg;
-			if (chanp->debug & 1) {
-				sprintf(tmp, "SUSPEND %s", ic->parm.num);
-				link_debug(chanp, tmp, 1);
-			}
-			FsmEvent(&chanp->fi, EV_SUSPEND, ic);
-			break;
-		case (ISDN_CMD_RESUME):
+		case (CAPI_PUT_MESSAGE):
X 			chanp = csta->channel + ic->arg;
-			if (chanp->debug & 1) {
-				sprintf(tmp, "RESUME %s", ic->parm.num);
-				link_debug(chanp, tmp, 1);
+			if (chanp->debug & 1)
+				capi_debug(chanp, &ic->parm.cmsg);
+			if (ic->parm.cmsg.Length < 8)
+				break;
+			switch(ic->parm.cmsg.Command) {
+				case CAPI_FACILITY:
+					if (ic->parm.cmsg.Subcommand == CAPI_REQ)
+						lli_got_fac_req(chanp, &ic->parm.cmsg);
+					break;
+				case CAPI_MANUFACTURER:
+					if (ic->parm.cmsg.Subcommand == CAPI_REQ)
+						lli_got_manufacturer(chanp, csta, &ic->parm.cmsg);
+					break;
+				default:
+					break;
X 			}
-			FsmEvent(&chanp->fi, EV_RESUME, ic);
X 			break;
X 		case (ISDN_CMD_LOCK):
X 			HiSax_mod_inc_use_count();
X #ifdef MODULE
-			if (csta->channel[0].debug & 0x400) {
-				jiftime(tmp, jiffies);
-				i = strlen(tmp);
-				sprintf(tmp + i, "   LOCK modcnt %d\n", MOD_USE_COUNT);
-				HiSax_putstatus(csta, tmp);
-			}
+			if (csta->channel[0].debug & 0x400)
+				HiSax_putstatus(csta, "   LOCK ", "modcnt %x",
+					MOD_USE_COUNT);
X #endif				/* MODULE */
X 			break;
X 		case (ISDN_CMD_UNLOCK):
X 			HiSax_mod_dec_use_count();
X #ifdef MODULE
-			if (csta->channel[0].debug & 0x400) {
-				jiftime(tmp, jiffies);
-				i = strlen(tmp);
-				sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT);
-				HiSax_putstatus(csta, tmp);
-			}
+			if (csta->channel[0].debug & 0x400)
+				HiSax_putstatus(csta, " UNLOCK ", "modcnt %x",
+					MOD_USE_COUNT);
X #endif				/* MODULE */
X 			break;
X 		case (ISDN_CMD_IOCTL):
@@ -2081,19 +1890,19 @@
X 				case (1):
X 					num = *(unsigned int *) ic->parm.num;
X 					distr_debug(csta, num);
-					sprintf(tmp, "debugging flags card %d set to %x\n",
+					printk(KERN_DEBUG "HiSax: debugging flags card %d set to %x\n",
X 						csta->cardnr + 1, num);
-					HiSax_putstatus(csta, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
+					HiSax_putstatus(csta, "debugging flags ",
+						"card %d set to %x", csta->cardnr + 1, num);
X 					break;
X 				case (2):
-					num = *(unsigned int *) ic->parm.num; 
-					csta->channel[0].lc_b->delay = num;
-					csta->channel[1].lc_b->delay = num;
-					sprintf(tmp, "delay card %d set to %d ms\n",
+					num = *(unsigned int *) ic->parm.num;
+					csta->channel[0].b_st->l1.delay = num;
+					csta->channel[1].b_st->l1.delay = num;
+					HiSax_putstatus(csta, "delay ", "card %d set to %d ms",
+						csta->cardnr + 1, num);
+					printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n",
X 						csta->cardnr + 1, num);
-					HiSax_putstatus(csta, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
X 					break;
X 				case (3):
X 					for (i = 0; i < *(unsigned int *) ic->parm.num; i++)
@@ -2106,47 +1915,91 @@
X 				case (5):	/* set card in leased mode */
X 					num = *(unsigned int *) ic->parm.num;
X 					if ((num <1) || (num > 2)) {
-						sprintf(tmp, "Set LEASED wrong channel %d\n",
+						HiSax_putstatus(csta, "Set LEASED ",
+							"wrong channel %d", num);
+						printk(KERN_WARNING "HiSax: Set LEASED wrong channel %d\n",
X 							num);
-						HiSax_putstatus(csta, tmp);
-						printk(KERN_WARNING "HiSax: %s", tmp);
X 					} else {
X 						num--;
-						csta->channel[num].leased = 1;
-						csta->channel[num].lc_d->l2_establish = 0;
-						sprintf(tmp, "card %d channel %d set leased mode\n",
+						chanp = csta->channel +num;
+						chanp->leased = 1;
+						HiSax_putstatus(csta, "Card",
+							"%d channel %d set leased mode\n",
X 							csta->cardnr + 1, num + 1);
-						HiSax_putstatus(csta, tmp);
-						FsmEvent(&csta->channel[num].lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+						chanp->d_st->l1.l1l2 = leased_l1l2;
+						chanp->d_st->lli.l4l3 = leased_l4l3;
+						chanp->d_st->lli.l4l3(chanp->d_st,
+							DL_ESTABLISH | REQUEST, NULL);
X 					}
X 					break;
X 				case (6):	/* set B-channel test loop */
X 					num = *(unsigned int *) ic->parm.num;
X 					if (csta->stlist)
-						csta->stlist->ma.manl1(csta->stlist,
-							PH_TESTLOOP_REQ, (void *) num);
+						csta->stlist->l2.l2l1(csta->stlist,
+							PH_TESTLOOP | REQUEST, (void *) (long)num);
+					break;
+				case (7):	/* set card in PTP mode */
+					num = *(unsigned int *) ic->parm.num;
+					if (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
+						printk(KERN_ERR "HiSax PTP mode only with one TEI possible\n");
+					} else if (num) {
+						test_and_set_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
+						test_and_set_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
+						csta->channel[0].d_st->l2.tei = 0;
+						HiSax_putstatus(csta, "set card ", "in PTP mode");
+						printk(KERN_DEBUG "HiSax: set card in PTP mode\n");
+						printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
+						test_and_set_bit(FLG_START_D, &csta->channel[0].Flags);
+						test_and_set_bit(FLG_START_D, &csta->channel[1].Flags);
+						csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st,
+							DL_ESTABLISH | REQUEST, NULL);
+					} else {
+						test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
+						test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
+						HiSax_putstatus(csta, "set card ", "in PTMP mode");
+						printk(KERN_DEBUG "HiSax: set card in PTMP mode\n");
+					}
+					break;
+				case (8):	/* set card in FIXED TEI mode */
+					num = *(unsigned int *) ic->parm.num;
+					chanp = csta->channel + (num & 1);
+					num = num >>1;
+					test_and_set_bit(FLG_FIXED_TEI, &chanp->d_st->l2.flag);
+					chanp->d_st->l2.tei = num;
+					HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num);
+					printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n",
+						num);
+					break;
+				case (9): /* load firmware */
+					memcpy(&adr, ic->parm.num, sizeof(ulong));
+					csta->cardmsg(csta, CARD_LOAD_FIRM,
+						(void *) adr);
X 					break;
X #ifdef MODULE
X 				case (55):
X 					while ( MOD_USE_COUNT > 0)
-                                           MOD_DEC_USE_COUNT;
+						MOD_DEC_USE_COUNT;
X 					HiSax_mod_inc_use_count();
X 					break;
X #endif				/* MODULE */
X 				case (11):
+					num = csta->debug & DEB_DLOG_HEX;
X 					csta->debug = *(unsigned int *) ic->parm.num;
-					sprintf(tmp, "l1 debugging flags card %d set to %x\n",
+					csta->debug |= num;
+					HiSax_putstatus(cards[0].cs, "l1 debugging ",
+						"flags card %d set to %x",
+						csta->cardnr + 1, csta->debug);
+					printk(KERN_DEBUG "HiSax: l1 debugging flags card %d set to %x\n",
X 						csta->cardnr + 1, csta->debug);
-					HiSax_putstatus(cards[0].cs, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
X 					break;
X 				case (13):
X 					csta->channel[0].d_st->l3.debug = *(unsigned int *) ic->parm.num;
X 					csta->channel[1].d_st->l3.debug = *(unsigned int *) ic->parm.num;
-					sprintf(tmp, "l3 debugging flags card %d set to %x\n",
+					HiSax_putstatus(cards[0].cs, "l3 debugging ",
+						"flags card %d set to %x\n", csta->cardnr + 1,
+						*(unsigned int *) ic->parm.num);
+					printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n",
X 						csta->cardnr + 1, *(unsigned int *) ic->parm.num);
-					HiSax_putstatus(cards[0].cs, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
X 					break;
X 				default:
X 					printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
@@ -2170,7 +2023,6 @@
X 	int len = skb->len;
X 	unsigned long flags;
X 	struct sk_buff *nskb;
-	char tmp[64];
X 
X 	if (!csta) {
X 		printk(KERN_ERR
@@ -2180,13 +2032,13 @@
X 	chanp = csta->channel + chan;
X 	st = chanp->b_st;
X 	if (!chanp->data_open) {
-		link_debug(chanp, "writebuf: channel not open", 1);
+		link_debug(chanp, 1, "writebuf: channel not open");
X 		return -EIO;
X 	}
X 	if (len > MAX_DATA_SIZE) {
-		sprintf(tmp, "writebuf: packet too large (%d bytes)", len);
-		printk(KERN_WARNING "HiSax_%s !\n", tmp);
-		link_debug(chanp, tmp, 1);
+		link_debug(chanp, 1, "writebuf: packet too large (%d bytes)", len);
+		printk(KERN_WARNING "HiSax_writebuf: packet too large (%d bytes) !\n",
+			len);
X 		return -EINVAL;
X 	}
X 	if (len) {
@@ -2194,10 +2046,8 @@
X 			/* Must return 0 here, since this is not an error
X 			 * but a temporary lack of resources.
X 			 */
-			if (chanp->debug & 0x800) {
-				sprintf(tmp, "writebuf: no buffers for %d bytes", len);
-				link_debug(chanp, tmp, 1);
-			}
+			if (chanp->debug & 0x800)
+				link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len);
X 			return 0;
X 		}
X 		save_flags(flags);
@@ -2206,11 +2056,11 @@
X 		if (nskb) {
X 			if (!ack)
X 				nskb->pkt_type = PACKET_NOACK;
-			if (chanp->lc_b->l2_establish)
-				st->l3.l3l2(st, DL_DATA, nskb);
+			if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I)
+				st->l3.l3l2(st, DL_DATA | REQUEST, nskb);
X 			else {
X 				chanp->bcs->tx_cnt += len;
-				st->l2.l2l1(st, PH_DATA_REQ, nskb);
+				st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
X 			}
X 			dev_kfree_skb(skb);
X 		} else
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/cert.c linux/drivers/isdn/hisax/cert.c
--- v2.3.3/linux/drivers/isdn/hisax/cert.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/cert.c	Sun May 23 10:03:41 1999
@@ -0,0 +1,55 @@
+/* $Id: cert.c,v 2.1 1998/11/15 23:51:15 keil Exp $
+
+ * Author       Karsten Keil (ke...@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
+ * $Log: cert.c,v $
+ * Revision 2.1  1998/11/15 23:51:15  keil
+ * certification stuff
+ *
+ * Revision 1.2.2.1  1998/11/03 21:46:37  keil
+ * first version
+ *
+ *
+ */
+ 
+#include <linux/kernel.h>
+
+int
+certification_check(int output) {
+
+#ifdef CERTIFICATION
+#if CERTIFICATION == 0
+	if (output) {
+		printk(KERN_INFO "HiSax: Approval certification valid\n");
+		printk(KERN_INFO "HiSax: Approved with ELSA Quickstep series cards\n");
+		printk(KERN_INFO "HiSax: Approval registration numbers:\n");
+		printk(KERN_INFO "HiSax: German D133361J CETECOM ICT Services GmbH\n");
+		printk(KERN_INFO "HiSax: EU (D133362J) CETECOM ICT Services GmbH\n");
+	}
+	return(0);
+#endif
+#if CERTIFICATION == 1
+	if (output) {
+		printk(KERN_INFO "HiSax: Approval certification failed because of\n");
+		printk(KERN_INFO "HiSax: unauthorized source code changes\n");
+	}
+	return(1);
+#endif
+#if CERTIFICATION == 127
+	if (output) {
+		printk(KERN_INFO "HiSax: Approval certification not possible\n");
+		printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n");
+	}
+	return(2);
+#endif
+#else
+	if (output) {
+		printk(KERN_INFO "HiSax: Certification not verified\n");
+	}
+	return(3);
+#endif
+}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.3.3/linux/drivers/isdn/hisax/config.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/isdn/hisax/config.c	Sun May 23 10:03:41 1999
@@ -1,10 +1,50 @@
-/* $Id: config.c,v 2.12 1998/02/11 17:28:02 keil Exp $
+/* $Id: config.c,v 2.23 1999/02/17 10:53:02 cpetig Exp $
X 
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *              based on the teles driver from Jan den Ouden
X  *
X  *
X  * $Log: config.c,v $
+ * Revision 2.23  1999/02/17 10:53:02  cpetig
+ * Added Hisax_closecard to exported symbols.
+ * As indicated by Oliver Schoett <o...@sdm.de>.
+ *
+ * If anyone is annoyed by exporting symbols deep inside the code, please
+ * contact me.
+ *
+ * Revision 2.22  1999/02/04 21:41:53  keil
+ * Fix printk msg
+ *
+ * Revision 2.21  1999/02/04 10:48:52  keil
+ * Fix readstat bug
+ *
+ * Revision 2.20  1998/11/15 23:54:28  keil
+ * changes from 2.0
+ *
+ * Revision 2.19  1998/08/13 23:36:18  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.18  1998/07/30 21:01:37  niemann
+ * Fixed Sedlbauer Speed Fax PCMCIA missing isdnl3new
+ *
+ * Revision 2.17  1998/07/15 15:01:26  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.16  1998/05/25 14:10:03  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.15  1998/05/25 12:57:43  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.14  1998/04/15 16:38:25  keil
+ * Add S0Box and Teles PCI support
+ *
+ * Revision 2.13  1998/03/09 23:19:23  keil
+ * Changes for PCMCIA
+ *
X  * Revision 2.12  1998/02/11 17:28:02  keil
X  * Niccy PnP/PCI support
X  *
@@ -55,6 +95,12 @@
X #include <linux/timer.h>
X #include <linux/config.h>
X #include "hisax.h"
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#define HISAX_STATUS_BUFSIZE 4096
+#define INCLUDE_INLINE_FUNCS
X 
X /*
X  * This structure array contains one entry per card. An entry looks
@@ -78,42 +124,78 @@
X  *   13 Teleint          p0=irq p1=iobase
X  *   14 Teles 16.3c      p0=irq p1=iobase
X  *   15 Sedlbauer speed  p0=irq p1=iobase
+ *   15 Sedlbauer PC/104	p0=irq p1=iobase
+ *   15 Sedlbauer speed pci	no parameter
X  *   16 USR Sportster internal  p0=irq  p1=iobase
X  *   17 MIC card                p0=irq  p1=iobase
X  *   18 ELSA Quickstep 1000PCI  no parameter
X  *   19 Compaq ISDN S0 ISA card p0=irq  p1=IO0 (HSCX)  p2=IO1 (ISAC) p3=IO2
X  *   20 Travers Technologies NETjet PCI card
- *   21 reserved TELES PCI
+ *   21 TELES PCI               no parameter
X  *   22 Sedlbauer Speed Star    p0=irq p1=iobase
X  *   23 reserved
X  *   24 Dr Neuhaus Niccy PnP/PCI card p0=irq p1=IO0 p2=IO1 (PnP only)
- *
+ *   25 Teles S0Box             p0=irq p1=iobase (from isapnp setup)
+ *   26 AVM A1 PCMCIA (Fritz)   p0=irq p1=iobase
+ *   27 AVM PnP/PCI 		p0=irq p1=iobase (PCI no parameter)
+ *   28 Sedlbauer Speed Fax+ 	p0=irq p1=iobase (from isapnp setup)
X  *
X  * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
X  *
X  *
X  */
X 
+const char *CardType[] =
+{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP",
+ "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2",
+ "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c",
+ "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
+ "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
+ "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
+ "Sedlbauer Speed Fax +"
+};
+
X #ifdef CONFIG_HISAX_ELSA
X #define DEFAULT_CARD ISDN_CTYPE_ELSA
X #define DEFAULT_CFG {0,0,0,0}
-#ifdef MODULE
X int elsa_init_pcmcia(void*, int, int*, int);
X EXPORT_SYMBOL(elsa_init_pcmcia);
X #endif
-#endif
X #ifdef CONFIG_HISAX_AVM_A1
X #undef DEFAULT_CARD
X #undef DEFAULT_CFG
X #define DEFAULT_CARD ISDN_CTYPE_A1
X #define DEFAULT_CFG {10,0x340,0,0}
X #endif
+
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
+#define DEFAULT_CFG {11,0x170,0,0}
+int avm_a1_init_pcmcia(void*, int, int*, int);
+EXPORT_SYMBOL(avm_a1_init_pcmcia);
+#endif
+
+#ifdef CONFIG_HISAX_FRITZPCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_FRITZPCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
X #ifdef CONFIG_HISAX_16_3
X #undef DEFAULT_CARD
X #undef DEFAULT_CFG
X #define DEFAULT_CARD ISDN_CTYPE_16_3
X #define DEFAULT_CFG {15,0x180,0,0}
X #endif
+#ifdef CONFIG_HISAX_S0BOX
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_S0BOX
+#define DEFAULT_CFG {7,0x378,0,0}
+#endif
X #ifdef CONFIG_HISAX_16_0
X #undef DEFAULT_CARD
X #undef DEFAULT_CFG
@@ -121,6 +203,13 @@
X #define DEFAULT_CFG {15,0xd0000,0xd80,0}
X #endif
X 
+#ifdef CONFIG_HISAX_TELESPCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_TELESPCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
X #ifdef CONFIG_HISAX_IX1MICROR2
X #undef DEFAULT_CARD
X #undef DEFAULT_CFG
@@ -193,13 +282,6 @@
X #define DEFAULT_CFG {12,0x3e0,0,0}
X #endif
X 
-#ifdef CONFIG_HISAX_DBRI
-#undef DEFAULT_CARD
-#undef DEFAULT_CFG
-#define DEFAULT_CARD ISDN_CTYPE_DBRI
-#define DEFAULT_CFG {0,0x0,0,0}
-#endif
-
X #ifdef CONFIG_HISAX_NICCY
X #undef DEFAULT_CARD
X #undef DEFAULT_CFG
@@ -232,10 +314,10 @@
X #endif
X 
X #define FIRST_CARD { \
-  DEFAULT_CARD, \
-  DEFAULT_PROTO, \
-  DEFAULT_CFG, \
-  NULL, \
+	DEFAULT_CARD, \
+	DEFAULT_PROTO, \
+	DEFAULT_CFG, \
+	NULL, \
X }
X 
X #define EMPTY_CARD	{0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
@@ -250,29 +332,20 @@
X 	EMPTY_CARD,
X 	EMPTY_CARD,
X 	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
X };
X 
-static char HiSaxID[96] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
+static char HiSaxID[64] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
X "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
X char *HiSax_id HISAX_INITDATA = HiSaxID;
X #ifdef MODULE
X /* Variables for insmod */
X static int type[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X static int protocol[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X static int io[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X #undef IO0_IO1
X #ifdef CONFIG_HISAX_16_3
X #define IO0_IO1
@@ -283,29 +356,29 @@
X #endif
X #ifdef IO0_IO1
X static int io0[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X static int io1[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X #endif
X static int irq[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X static int mem[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
X static char *id HISAX_INITDATA = HiSaxID;
X 
X MODULE_AUTHOR("Karsten Keil");
-MODULE_PARM(type, "1-3i");
-MODULE_PARM(protocol, "1-2i");
+MODULE_PARM(type, "1-8i");
+MODULE_PARM(protocol, "1-8i");
X MODULE_PARM(io, "1-8i");
-MODULE_PARM(irq, "1-2i");
-MODULE_PARM(mem, "1-12i");
+MODULE_PARM(irq, "1-8i");
+MODULE_PARM(mem, "1-8i");
X MODULE_PARM(id, "s");
X #ifdef CONFIG_HISAX_16_3	/* For Creatix/Teles PnP */
X MODULE_PARM(io0, "1-8i");
X MODULE_PARM(io1, "1-8i");
-#endif
+#endif /* CONFIG_HISAX_16_3 */
X 
-#endif
+#endif /* MODULE */
X 
X int nrcards;
X 
@@ -333,23 +406,25 @@
X HISAX_INITFUNC(void
X HiSaxVersion(void))
X {
-	char tmp[64], rev[64];
-	char *r = rev;
+	char tmp[64];
X 
+	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
+#ifdef MODULE
+	printk(KERN_INFO "HiSax: Version 3.1a (module)\n");
+#else
+	printk(KERN_INFO "HiSax: Version 3.1a (kernel)\n");
+#endif
X 	strcpy(tmp, l1_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
X 	strcpy(tmp, l2_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Layer2 Revision %s\n", HiSax_getrev(tmp));
+	strcpy(tmp, tei_revision);
+	printk(KERN_INFO "HiSax: TeiMgr Revision %s\n", HiSax_getrev(tmp));
X 	strcpy(tmp, l3_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp));
X 	strcpy(tmp, lli_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
-	strcpy(tmp, tei_revision);
-	r += sprintf(r, "%s", HiSax_getrev(tmp));
-
-	printk(KERN_INFO "HiSax: Driver for Siemens chip set ISDN cards\n");
-	printk(KERN_INFO "HiSax: Version 2.8\n");
-	printk(KERN_INFO "HiSax: Revisions %s\n", rev);
+	printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp));
+	certification_check(1);
X }
X 
X void
@@ -375,7 +450,7 @@
X 	argc = ints[0];
X 	i = 0;
X 	j = 1;
-	while (argc && (i < 16)) {
+	while (argc && (i < HISAX_MAX_CARDS)) {
X 		if (argc) {
X 			cards[i].typ = ints[j];
X 			j++;
@@ -413,11 +488,759 @@
X }
X #endif
X 
+#if CARD_TELES0
+extern int setup_teles0(struct IsdnCard *card);
+#endif
+
+#if CARD_TELES3
+extern int setup_teles3(struct IsdnCard *card);
+#endif
+
+#if CARD_S0BOX
+extern int setup_s0box(struct IsdnCard *card);
+#endif
+
+#if CARD_TELESPCI
+extern int setup_telespci(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1
+extern int setup_avm_a1(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1_PCMCIA
+extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
+#endif
+
+#if CARD_FRITZPCI
+extern int setup_avm_pcipnp(struct IsdnCard *card);
+#endif
+
+#if CARD_ELSA
+extern int setup_elsa(struct IsdnCard *card);
+#endif
+
+#if CARD_IX1MICROR2
+extern int setup_ix1micro(struct IsdnCard *card);
+#endif
+
+#if CARD_DIEHLDIVA
+extern	int  setup_diva(struct IsdnCard *card);
+#endif
+
+#if CARD_ASUSCOM
+extern int setup_asuscom(struct IsdnCard *card);
+#endif
+
+#if CARD_TELEINT
+extern int setup_TeleInt(struct IsdnCard *card);
+#endif
+
+#if CARD_SEDLBAUER
+extern int setup_sedlbauer(struct IsdnCard *card);
+#endif
+
+#if CARD_SPORTSTER
+extern int setup_sportster(struct IsdnCard *card);
+#endif
+
+#if CARD_MIC
+extern int setup_mic(struct IsdnCard *card);
+#endif
+
+#if CARD_NETJET
+extern int setup_netjet(struct IsdnCard *card);
+#endif
+
+#if CARD_TELES3C
+extern int setup_t163c(struct IsdnCard *card);
+#endif
+
+#if CARD_AMD7930
+extern int setup_amd7930(struct IsdnCard *card);
+#endif
+
+#if CARD_NICCY
+extern int setup_niccy(struct IsdnCard *card);
+#endif
+
+/*
+ * Find card with given driverId
+ */
+static inline struct IsdnCardState
+*hisax_findcard(int driverid)
+{
+	int i;
+
+	for (i = 0; i < nrcards; i++)
+		if (cards[i].cs)
+			if (cards[i].cs->myid == driverid)
+				return (cards[i].cs);
+	return (NULL);
+}
+
+int
+HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
+{
+	int count,cnt;
+	u_char *p = buf;
+	struct IsdnCardState *cs = hisax_findcard(id);
+
+	if (cs) {
+		if (len > HISAX_STATUS_BUFSIZE) {
+			printk(KERN_WARNING "HiSax: status overflow readstat %d/%d\n",
+				len, HISAX_STATUS_BUFSIZE);
+		}
+		count = cs->status_end - cs->status_read +1;
+		if (count >= len)
+			count = len;
+		if (user)
+			copy_to_user(p, cs->status_read, count);
+		else
+			memcpy(p, cs->status_read, count);
+		cs->status_read += count;
+		if (cs->status_read > cs->status_end)
+			cs->status_read = cs->status_buf;
+		p += count;
+		count = len - count;
+		while (count) {
+			if (count > HISAX_STATUS_BUFSIZE)
+				cnt = HISAX_STATUS_BUFSIZE;
+			else
+				cnt = count;
+			if (user)
+				copy_to_user(p, cs->status_read, cnt);
+			else
+				memcpy(p, cs->status_read, cnt);
+			p += cnt;
+			cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
+			count -= cnt;
+		}
+		return len;
+	} else {
+		printk(KERN_ERR
+		 "HiSax: if_readstatus called with invalid driverId!\n");
+		return -ENODEV;
+	}
+}
+
+inline int
+jiftime(char *s, long mark)
+{
+	s += 8;
+
+	*s-- = '\0';
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = '.';
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = mark % 6 + '0';
+	mark /= 6;
+	*s-- = ':';
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = mark % 10 + '0';
+	return(8);
+}
+
+static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
+
+void
+VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args)
+{
+/* if head == NULL the fmt contains the full info */
+
+	long flags;
+	int count, i;
+	u_char *p;
+	isdn_ctrl ic;
+	int len;
+
+	save_flags(flags);
+	cli();
+	p = tmpbuf;
+	if (head) {
+		p += jiftime(p, jiffies);
+		p += sprintf(p, " %s", head);
+		p += vsprintf(p, fmt, args);
+		*p++ = '\n';
+		*p = 0;
+		len = p - tmpbuf;
+		p = tmpbuf;
+	} else {
+		p = fmt;
+		len = strlen(fmt);
+	}
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: No CardStatus for message %s", p);
+		restore_flags(flags);
+		return;
+	}
+	if (len > HISAX_STATUS_BUFSIZE) {
+		printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
+			len, HISAX_STATUS_BUFSIZE);
+		restore_flags(flags);
+		return;
+	}
+	count = len;
+	i = cs->status_end - cs->status_write +1;
+	if (i >= len)
+		i = len;
+	len -= i;
+	memcpy(cs->status_write, p, i);
+	cs->status_write += i;
+	if (cs->status_write > cs->status_end)
+		cs->status_write = cs->status_buf;
+	p += i;
+	if (len) {
+		memcpy(cs->status_write, p, len);
+		cs->status_write += len;
+	}
+#ifdef KERNELSTACK_DEBUG
+	i = (ulong)&len - current->kernel_stack_page;
+	sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm,
+		current->kernel_stack_page, i);
+	len = strlen(tmpbuf);
+	for (p = tmpbuf, i = len; i > 0; i--, p++) {
+		*cs->status_write++ = *p;
+		if (cs->status_write > cs->status_end)
+			cs->status_write = cs->status_buf;
+		count++;
+	}
+#endif
+	restore_flags(flags);
+	if (count) {
+		ic.command = ISDN_STAT_STAVAIL;
+		ic.driver = cs->myid;
+		ic.arg = count;
+		cs->iif.statcallb(&ic);
+	}
+}
+
+void
+HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	VHiSax_putstatus(cs, head, fmt, args);
+	va_end(args);
+}
+
+int
+ll_run(struct IsdnCardState *cs)
+{
+	long flags;
+	isdn_ctrl ic;
+
+	save_flags(flags);
+	cli();
+	ic.driver = cs->myid;
+	ic.command = ISDN_STAT_RUN;
+	cs->iif.statcallb(&ic);
+	restore_flags(flags);
+	return 0;
+}
+
+void
+ll_stop(struct IsdnCardState *cs)
+{
+	isdn_ctrl ic;
+
+	ic.command = ISDN_STAT_STOP;
+	ic.driver = cs->myid;
+	cs->iif.statcallb(&ic);
+	CallcFreeChan(cs);
+}
+
+static void
+ll_unload(struct IsdnCardState *cs)
+{
+	isdn_ctrl ic;
+
+	ic.command = ISDN_STAT_UNLOAD;
+	ic.driver = cs->myid;
+	cs->iif.statcallb(&ic);
+	if (cs->status_buf)
+		kfree(cs->status_buf);
+	cs->status_read = NULL;
+	cs->status_write = NULL;
+	cs->status_end = NULL;
+	kfree(cs->dlog);
+}
+
+static void
+closecard(int cardnr)
+{
+	struct IsdnCardState *csta = cards[cardnr].cs;
+
+	if (csta->bcs->BC_Close != NULL) {
+		csta->bcs->BC_Close(csta->bcs + 1);
+		csta->bcs->BC_Close(csta->bcs);
+	}
+
+	if (csta->rcvbuf) {
+		kfree(csta->rcvbuf);
+		csta->rcvbuf = NULL;
+	}
+	discard_queue(&csta->rq);
+	discard_queue(&csta->sq);
+	if (csta->tx_skb) {
+		dev_kfree_skb(csta->tx_skb);
+		csta->tx_skb = NULL;
+	}
+	if (csta->mon_rx) {
+		kfree(csta->mon_rx);
+		csta->mon_rx = NULL;
+	}
+	if (csta->mon_tx) {
+		kfree(csta->mon_tx);
+		csta->mon_tx = NULL;
+	}
+	csta->cardmsg(csta, CARD_RELEASE, NULL);
+	if (csta->dbusytimer.function != NULL)
+		del_timer(&csta->dbusytimer);
+	ll_unload(csta);
+}
+
+HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
+{
+	int irq_cnt, cnt = 3;
+	long flags;
+
+	save_flags(flags);
+	cli();
+	irq_cnt = kstat_irqs(cs->irq);
+	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
+		irq_cnt);
+	if (cs->cardmsg(cs, CARD_SETIRQ, NULL)) {
+		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
+			cs->irq);
+		restore_flags(flags);
+		return(1);
+	}
+	while (cnt) {
+		cs->cardmsg(cs, CARD_INIT, NULL);
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 18'
echo 'File patch-2.3.4 is continued in part 19'
echo 19 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 20 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 20; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void mshutdown(struct IsdnCardState *cs)
+{
+	unsigned long	flags;
+
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk(KERN_DEBUG"Shutting down serial ....");
+#endif
+	
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+
+	cs->hw.elsa.IER = 0;
+	serial_outp(cs, UART_IER, 0x00);	/* disable all intrs */
+	cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
+	
+	/* disable break condition */
+	serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
+	
+	cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
+
+	/* disable FIFO's */	
+	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
+	serial_inp(cs, UART_RX);    /* read data port to reset things */
+	
+	restore_flags(flags);
+#ifdef SERIAL_DEBUG_OPEN
+	printk(" done\n");
+#endif
+}
+
+inline int
+write_modem(struct BCState *bcs) {
+	int ret=0;
+	struct IsdnCardState *cs = bcs->cs;
+	int count, len, fp, buflen;
+	long flags;
+	
+	if (!bcs->tx_skb)
+		return 0;
+	if (bcs->tx_skb->len <= 0)
+		return 0;
+	save_flags(flags);
+	cli();
+	buflen = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
+	len = MIN(buflen, bcs->tx_skb->len);		
+	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
+	fp &= (MAX_MODEM_BUF -1);
+	count = MIN(len, MAX_MODEM_BUF - fp);
+	if (count < len) {
+		memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count);
+		skb_pull(bcs->tx_skb, count);
+		cs->hw.elsa.transcnt += count;
+		ret = count;
+		count = len - count;
+		fp = 0;
+	}
+	memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count);
+	skb_pull(bcs->tx_skb, count);
+	cs->hw.elsa.transcnt += count;
+	ret += count;
+	
+	if (cs->hw.elsa.transcnt && 
+	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
+			cs->hw.elsa.IER |= UART_IER_THRI;
+		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+	}
+	restore_flags(flags);
+	return(ret);
+}
+
+inline void
+modem_fill(struct BCState *bcs) {
+		
+	if (bcs->tx_skb) {
+		if (bcs->tx_skb->len) {
+			write_modem(bcs);
+			return;
+		} else {
+			if (bcs->st->lli.l1writewakeup &&
+				(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st,
+						bcs->hw.hscx.count);
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+		}
+	}
+	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+		bcs->hw.hscx.count = 0;
+		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+		write_modem(bcs);
+	} else {
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		hscx_sched_event(bcs, B_XMTBUFREADY);
+	}
+}
+
+static inline void receive_chars(struct IsdnCardState *cs,
+				 int *status)
+{
+	unsigned char ch;
+	struct sk_buff *skb;
+
+	do {
+		ch = serial_in(cs, UART_RX);
+		if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF)
+			break;
+		cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch;
+#ifdef SERIAL_DEBUG_INTR
+		printk("DR%02x:%02x...", ch, *status);
+#endif
+		if (*status & (UART_LSR_BI | UART_LSR_PE |
+			       UART_LSR_FE | UART_LSR_OE)) {
+					
+#ifdef SERIAL_DEBUG_INTR
+			printk("handling exept....");
+#endif
+		}
+		*status = serial_inp(cs, UART_LSR);
+	} while (*status & UART_LSR_DR);
+	if (cs->hw.elsa.MFlag == 2) {
+		if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt)))
+			printk(KERN_WARNING "ElsaSER: receive out of memory\n");
+		else {
+			memcpy(skb_put(skb, cs->hw.elsa.rcvcnt), cs->hw.elsa.rcvbuf, 
+				cs->hw.elsa.rcvcnt);
+			skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
+		}
+		hscx_sched_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
+	} else {
+		char tmp[128];
+		char *t = tmp;
+
+		t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
+		QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
+		debugl1(cs, tmp);
+	}
+	cs->hw.elsa.rcvcnt = 0;
+}
+
+static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
+{
+	int count;
+	
+	debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp, 
+		cs->hw.elsa.transcnt);
+	
+	if (cs->hw.elsa.transcnt <= 0) {
+		cs->hw.elsa.IER &= ~UART_IER_THRI;
+		serial_out(cs, UART_IER, cs->hw.elsa.IER);
+		return;
+	}
+	count = 16;
+	do {
+		serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
+		if (cs->hw.elsa.transp >= MAX_MODEM_BUF)
+			cs->hw.elsa.transp=0;
+		if (--cs->hw.elsa.transcnt <= 0)
+			break;
+	} while (--count > 0);
+	if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag==2))
+		modem_fill(cs->hw.elsa.bcs);
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+	if (intr_done)
+		*intr_done = 0;
+	if (cs->hw.elsa.transcnt <= 0) {
+		cs->hw.elsa.IER &= ~UART_IER_THRI;
+		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+	}
+}
+
+#if 0
+static inline void check_modem_status(struct IsdnCardState *cs)
+{
+	int	status;
+	struct async_struct *info = cs->hw.elsa.info;
+	struct	async_icount *icount;
+	
+	status = serial_inp(info, UART_MSR);
+
+	if (status & UART_MSR_ANY_DELTA) {
+		icount = &info->state->icount;
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			icount->rng++;
+		if (status & UART_MSR_DDSR)
+			icount->dsr++;
+		if (status & UART_MSR_DDCD) {
+			icount->dcd++;
+		}
+		if (status & UART_MSR_DCTS)
+			icount->cts++;
+//		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttys%d CD now %s...", info->line,
+		       (status & UART_MSR_DCD) ? "on" : "off");
+#endif		
+		if (status & UART_MSR_DCD)
+//			wake_up_interruptible(&info->open_wait);
+;
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("doing serial hangup...");
+#endif
+			if (info->tty)
+				tty_hangup(info->tty);
+		}
+	}
+#if 0
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				serial_outp(info, UART_IER, info->IER);
+//				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				serial_outp(info, UART_IER, info->IER);
+			}
+		}
+	}
+#endif 0
+}
+#endif
+
+static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
+{
+	int status, iir, msr;
+	int pass_counter = 0;
+	
+#ifdef SERIAL_DEBUG_INTR
+	printk("rs_interrupt_single(%d)...", irq);
+#endif
+
+	do {
+		status = serial_inp(cs, UART_LSR);
+		debugl1(cs,"rs LSR %02x", status);
+#ifdef SERIAL_DEBUG_INTR
+		printk("status = %x...", status);
+#endif
+		if (status & UART_LSR_DR)
+			receive_chars(cs, &status);
+		if (status & UART_LSR_THRE)
+			transmit_chars(cs, 0);
+		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+			printk("rs_single loop break.\n");
+			break;
+		}
+		iir = serial_inp(cs, UART_IIR);
+		debugl1(cs,"rs IIR %02x", iir);
+		if ((iir & 0xf) == 0) {
+			msr = serial_inp(cs, UART_MSR);
+			debugl1(cs,"rs MSR %02x", msr);
+		}
+	} while (!(iir & UART_IIR_NO_INT));
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+
+extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
+extern void modehscx(struct BCState *bcs, int mode, int bc);
+extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
+
+void
+close_elsastate(struct BCState *bcs)
+{
+	struct sk_buff *skb;
+
+	modehscx(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.hscx.rcvbuf) {
+			if (bcs->mode != L1_MODE_MODEM)
+				kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+		}
+		while ((skb = skb_dequeue(&bcs->rqueue))) {
+			dev_kfree_skb(skb);
+		}
+		while ((skb = skb_dequeue(&bcs->squeue))) {
+			dev_kfree_skb(skb);
+		}
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+void
+modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
+	int count, fp;
+	u_char *msg = buf;
+	long flags;
+	
+	if (!len)
+		return;
+	save_flags(flags);
+	cli();		
+	if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
+		restore_flags(flags);
+		return;
+	}
+	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
+	fp &= (MAX_MODEM_BUF -1);
+	count = MIN(len, MAX_MODEM_BUF - fp);
+	if (count < len) {
+		memcpy(cs->hw.elsa.transbuf + fp, msg, count);
+		cs->hw.elsa.transcnt += count;
+		msg += count;
+		count = len - count;
+		fp = 0;
+	}
+	memcpy(cs->hw.elsa.transbuf + fp, msg, count);
+	cs->hw.elsa.transcnt += count;
+	if (cs->hw.elsa.transcnt && 
+	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
+		cs->hw.elsa.IER |= UART_IER_THRI;
+		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+	}
+	restore_flags(flags);
+}
+
+void
+modem_set_init(struct IsdnCardState *cs) {
+	long flags;
+	int timeout;
+
+#define RCV_DELAY 20000	
+	save_flags(flags);
+	sti();
+	modem_write_cmd(cs, MInit_1, strlen(MInit_1));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_2, strlen(MInit_2));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_3, strlen(MInit_3));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_4, strlen(MInit_4));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY );
+	modem_write_cmd(cs, MInit_5, strlen(MInit_5));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_6, strlen(MInit_6));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_7, strlen(MInit_7));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	restore_flags(flags);
+}
+
+void
+modem_set_dial(struct IsdnCardState *cs, int outgoing) {
+	long flags;
+	int timeout;
+#define RCV_DELAY 20000	
+
+	save_flags(flags);
+	sti();
+	modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	if (outgoing)
+		modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
+	else
+		modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	restore_flags(flags);
+}
+
+void
+modem_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	if (pr == (PH_DATA | REQUEST)) {
+		save_flags(flags);
+		cli();
+		if (st->l1.bcs->tx_skb) {
+			skb_queue_tail(&st->l1.bcs->squeue, skb);
+			restore_flags(flags);
+		} else {
+			st->l1.bcs->tx_skb = skb;
+			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			st->l1.bcs->hw.hscx.count = 0;
+			restore_flags(flags);
+			write_modem(st->l1.bcs);
+		}
+	} else if (pr == (PH_ACTIVATE | REQUEST)) {
+		test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+		st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+		set_arcofi(st->l1.bcs->cs, st->l1.bc);
+		mstartup(st->l1.bcs->cs);
+		modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
+		st->l1.bcs->cs->hw.elsa.MFlag=2;
+	} else if (pr == (PH_DEACTIVATE | REQUEST)) {
+		test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+		send_arcofi(st->l1.bcs->cs, ARCOFI_XOP_0, st->l1.bc, 0);
+		st->l1.bcs->cs->hw.elsa.MFlag=1;
+	} else {
+		printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
+	}
+}
+
+int
+setstack_elsa(struct PStack *st, struct BCState *bcs)
+{
+
+	bcs->channel = st->l1.bc;
+	switch (st->l1.mode) {
+		case L1_MODE_HDLC:
+		case L1_MODE_TRANS:
+			if (open_hscxstate(st->l1.hardware, bcs))
+				return (-1);
+			st->l2.l2l1 = hscx_l2l1;
+			break;
+		case L1_MODE_MODEM:
+			bcs->mode = L1_MODE_MODEM;
+			if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+				bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
+				skb_queue_head_init(&bcs->rqueue);
+				skb_queue_head_init(&bcs->squeue);
+			}
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->event = 0;
+			bcs->hw.hscx.rcvidx = 0;
+			bcs->tx_cnt = 0;
+			bcs->cs->hw.elsa.bcs = bcs;
+			st->l2.l2l1 = modem_l2l1;
+			break;
+	}
+	st->l1.bcs = bcs;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+void
+init_modem(struct IsdnCardState *cs) {
+
+	cs->bcs[0].BC_SetStack = setstack_elsa;
+	cs->bcs[1].BC_SetStack = setstack_elsa;
+	cs->bcs[0].BC_Close = close_elsastate;
+	cs->bcs[1].BC_Close = close_elsastate;
+	if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
+		GFP_ATOMIC))) {
+		printk(KERN_WARNING
+			"Elsa: No modem mem hw.elsa.rcvbuf\n");
+		return;
+	}
+	if (!(cs->hw.elsa.transbuf = kmalloc(MAX_MODEM_BUF,
+		GFP_ATOMIC))) {
+		printk(KERN_WARNING
+			"Elsa: No modem mem hw.elsa.transbuf\n");
+		kfree(cs->hw.elsa.rcvbuf);
+		cs->hw.elsa.rcvbuf = NULL;
+		return;
+	}
+	if (mstartup(cs)) {
+		printk(KERN_WARNING "Elsa: problem startup modem\n");
+	}
+	modem_set_init(cs);
+}
+
+void
+release_modem(struct IsdnCardState *cs) {
+
+	cs->hw.elsa.MFlag = 0;
+	if (cs->hw.elsa.transbuf) {
+		if (cs->hw.elsa.rcvbuf) {
+			mshutdown(cs);
+			kfree(cs->hw.elsa.rcvbuf);
+			cs->hw.elsa.rcvbuf = NULL;
+		}
+		kfree(cs->hw.elsa.transbuf);
+		cs->hw.elsa.transbuf = NULL;
+	}
+}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/fsm.c linux/drivers/isdn/hisax/fsm.c
--- v2.3.3/linux/drivers/isdn/hisax/fsm.c	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/fsm.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: fsm.c,v 1.7 1997/11/06 17:09:13 keil Exp $
+/* $Id: fsm.c,v 1.10 1998/11/15 23:54:39 keil Exp $
X 
X  * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
X  *              based on the teles driver from Jan den Ouden
@@ -7,6 +7,18 @@
X  *              Fritz Elfert
X  *
X  * $Log: fsm.c,v $
+ * Revision 1.10  1998/11/15 23:54:39  keil
+ * changes from 2.0
+ *
+ * Revision 1.9  1998/03/26 07:10:02  paul
+ * The jumpmatrix table in struct Fsm was an array of "int". This is not
+ * large enough for pointers to functions on Linux/Alpha (instant crash
+ * on "insmod hisax). Now there is a typedef for the pointer to function.
+ * This also prevents warnings about "incompatible pointer types".
+ *
+ * Revision 1.8  1998/03/07 22:56:59  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
X  * Revision 1.7  1997/11/06 17:09:13  keil
X  * New 2.1 init code
X  *
@@ -41,18 +53,18 @@
X {
X 	int i;
X 
-	fsm->jumpmatrix = (int *)
-	    kmalloc(4L * fsm->state_count * fsm->event_count, GFP_KERNEL);
-	memset(fsm->jumpmatrix, 0, 4L * fsm->state_count * fsm->event_count);
+	fsm->jumpmatrix = (FSMFNPTR *)
+		kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
+	memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
X 
X 	for (i = 0; i < fncount; i++) 
X 		if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
-			printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n",
-				i,fnlist[i].state,fsm->state_count,
-				fnlist[i].event,fsm->event_count);
+			printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
+				i,(long)fnlist[i].state,(long)fsm->state_count,
+				(long)fnlist[i].event,(long)fsm->event_count);
X 		} else		
X 			fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
-				fnlist[i].state] = (int) fnlist[i].routine;
+				fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
X }
X 
X void
@@ -64,31 +76,26 @@
X int
X FsmEvent(struct FsmInst *fi, int event, void *arg)
X {
-	void (*r) (struct FsmInst *, int, void *);
-	char str[80];
+	FSMFNPTR r;
X 
X 	if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) {
-		printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n",
-			fi->state,fi->fsm->state_count,event,fi->fsm->event_count);
+		printk(KERN_ERR "FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
+			(long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count);
X 		return(1);
X 	}
-	r = (void (*)) fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
+	r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
X 	if (r) {
-		if (fi->debug) {
-			sprintf(str, "State %s Event %s",
+		if (fi->debug)
+			fi->printdebug(fi, "State %s Event %s",
X 				fi->fsm->strState[fi->state],
X 				fi->fsm->strEvent[event]);
-			fi->printdebug(fi, str);
-		}
X 		r(fi, event, arg);
X 		return (0);
X 	} else {
-		if (fi->debug) {
-			sprintf(str, "State %s Event %s no routine",
+		if (fi->debug)
+			fi->printdebug(fi, "State %s Event %s no routine",
X 				fi->fsm->strState[fi->state],
X 				fi->fsm->strEvent[event]);
-			fi->printdebug(fi, str);
-		}
X 		return (!0);
X 	}
X }
@@ -96,25 +103,18 @@
X void
X FsmChangeState(struct FsmInst *fi, int newstate)
X {
-	char str[80];
-
X 	fi->state = newstate;
-	if (fi->debug) {
-		sprintf(str, "ChangeState %s",
+	if (fi->debug)
+		fi->printdebug(fi, "ChangeState %s",
X 			fi->fsm->strState[newstate]);
-		fi->printdebug(fi, str);
-	}
X }
X 
X static void
X FsmExpireTimer(struct FsmTimer *ft)
X {
X #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmExpireTimer %lx", (long) ft);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
X #endif
X 	FsmEvent(ft->fi, ft->event, ft->arg);
X }
@@ -126,11 +126,8 @@
X 	ft->tl.function = (void *) FsmExpireTimer;
X 	ft->tl.data = (long) ft;
X #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmInitTimer %lx", (long) ft);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
X #endif
X 	init_timer(&ft->tl);
X }
@@ -139,11 +136,8 @@
X FsmDelTimer(struct FsmTimer *ft, int where)
X {
X #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmDelTimer %lx %d", (long) ft, where);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
X #endif
X 	del_timer(&ft->tl);
X }
@@ -154,11 +148,9 @@
X {
X 
X #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmAddTimer %lx %d %d", (long) ft, millisec, where);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
+			(long) ft, millisec, where);
X #endif
X 
X 	if (ft->tl.next || ft->tl.prev) {
@@ -180,11 +172,9 @@
X {
X 
X #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmRestartTimer %lx %d %d", (long) ft, millisec, where);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
+			(long) ft, millisec, where);
X #endif
X 
X 	if (ft->tl.next || ft->tl.prev)
@@ -194,25 +184,4 @@
X 	ft->arg = arg;
X 	ft->tl.expires = jiffies + (millisec * HZ) / 1000;
X 	add_timer(&ft->tl);
-}
-
-void
-jiftime(char *s, long mark)
-{
-	s += 8;
-
-	*s-- = '\0';
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = '.';
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = mark % 6 + '0';
-	mark /= 6;
-	*s-- = ':';
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = mark % 10 + '0';
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c
--- v2.3.3/linux/drivers/isdn/hisax/hfc_2bds0.c	Thu May 14 18:42:23 1998
+++ linux/drivers/isdn/hisax/hfc_2bds0.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.3 1998/02/12 23:07:22 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.8 1998/11/15 23:54:40 keil Exp $
X  *
X  *  specific routines for CCD's HFC 2BDS0
X  *
@@ -6,6 +6,22 @@
X  *
X  *
X  * $Log: hfc_2bds0.c,v $
+ * Revision 1.8  1998/11/15 23:54:40  keil
+ * changes from 2.0
+ *
+ * Revision 1.7  1998/09/30 22:24:45  keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6  1998/08/13 23:36:26  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5  1998/06/27 22:52:58  keil
+ * make 16.3c working with 3.0
+ *
+ * Revision 1.4  1998/05/25 12:57:52  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X * Revision 1.3 1998/02/12 23:07:22 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -46,11 +62,8 @@
X 		}
X 		ret = bytein(cs->hw.hfcD.addr);
X #if HFC_REG_DEBUG
-		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
-			char tmp[32];
-			sprintf(tmp, "t3c RD %02x %02x", reg, ret);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+			debugl1(cs, "t3c RD %02x %02x", reg, ret);
X #endif
X 	} else
X 		ret = bytein(cs->hw.hfcD.addr | 1);
@@ -67,11 +80,8 @@
X 	if (data)
X 		byteout(cs->hw.hfcD.addr, value);
X #if HFC_REG_DEBUG
-	if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB)) {
-		char tmp[16];
-		sprintf(tmp, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB))
+		debugl1(cs, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
X #endif
X }
X 
@@ -227,7 +237,6 @@
X 	int chksum;
X 	long flags;
X 	u_char stat, cip;
-	char tmp[64];
X 	
X 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
X 		debugl1(cs, "hfc_empty_fifo");
@@ -283,11 +292,9 @@
X 			WaitNoBusy(cs);
X 			stat = ReadReg(cs, HFCD_DATA, cip);
X 			sti();
-			if (cs->debug & L1_DEB_HSCX) {
-				sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x",
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
X 					bcs->channel, chksum, stat);
-				debugl1(cs, tmp);
-			}
X 			if (stat) {
X 				debugl1(cs, "FIFO CRC error");
X 				dev_kfree_skb(skb);
@@ -315,14 +322,11 @@
X 	int idx, fcnt;
X 	int count;
X 	u_char cip;
-	char tmp[64];
-	
X 
-	if (!bcs->hw.hfc.tx_skb)
+	if (!bcs->tx_skb)
X 		return;
-	if (bcs->hw.hfc.tx_skb->len <= 0)
+	if (bcs->tx_skb->len <= 0)
X 		return;
-
X 	save_flags(flags);
X 	cli();
X 	SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); 
@@ -335,12 +339,10 @@
X 	bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip);
X 	bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
X 	sti();
- 	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
+ 	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
X 			bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
X 			bcs->hw.hfc.send[bcs->hw.hfc.f1]);
-		debugl1(cs, tmp);
-	}
X 	fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
X 	if (fcnt < 0)
X 		fcnt += 32;
@@ -351,13 +353,11 @@
X 		return;
X 	}
X 	count = GetFreeFifoBytes_B(bcs);
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d count(%d/%d),%lx",
-			bcs->channel, bcs->hw.hfc.tx_skb->len,
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx",
+			bcs->channel, bcs->tx_skb->len,
X 			count, current->state);
-		debugl1(cs, tmp);
-	}
-	if (count < bcs->hw.hfc.tx_skb->len) {
+	if (count < bcs->tx_skb->len) {
X 		if (cs->debug & L1_DEB_HSCX)
X 			debugl1(cs, "hfc_fill_fifo no fifo mem");
X 		restore_flags(flags);
@@ -368,26 +368,26 @@
X 	cli();
X 	WaitForBusy(cs);
X 	WaitNoBusy(cs);
-	WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]);
-	while (idx < bcs->hw.hfc.tx_skb->len) {
+	WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+	while (idx < bcs->tx_skb->len) {
X 		cli();
X 		if (!WaitNoBusy(cs))
X 			break;
-		WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx]);
+		WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]);
X 		sti();
X 		idx++;
X 	}
-	if (idx != bcs->hw.hfc.tx_skb->len) {
+	if (idx != bcs->tx_skb->len) {
X 		sti();
X 		debugl1(cs, "FIFO Send BUSY error");
X 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
X 	} else {
-		bcs->tx_cnt -= bcs->hw.hfc.tx_skb->len;
+		bcs->tx_cnt -= bcs->tx_skb->len;
X 		if (bcs->st->lli.l1writewakeup &&
-			(PACKET_NOACK != bcs->hw.hfc.tx_skb->pkt_type))
-			bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hfc.tx_skb->len);
-		dev_kfree_skb(bcs->hw.hfc.tx_skb);
-		bcs->hw.hfc.tx_skb = NULL;
+			(PACKET_NOACK != bcs->tx_skb->pkt_type))
+			bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+		dev_kfree_skb(bcs->tx_skb);
+		bcs->tx_skb = NULL;
X 	}
X 	WaitForBusy(cs);
X 	cli();
@@ -404,15 +404,12 @@
X hfc_send_data(struct BCState *bcs)
X {
X 	struct IsdnCardState *cs = bcs->cs;
-	char tmp[32];
X 	
X 	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
X 		hfc_fill_fifo(bcs);
X 		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else {
-		sprintf(tmp,"send_data %d blocked", bcs->channel);
-		debugl1(cs, tmp);
-	}
+	} else
+		debugl1(cs,"send_data %d blocked", bcs->channel);
X }
X 
X void
@@ -424,15 +421,13 @@
X 	u_char f1, f2, cip;
X 	int receive, count = 5;
X 	struct sk_buff *skb;
-	char tmp[64];
X 
X 	save_flags(flags);
X     Begin:
X 	count--;
X 	cli();
X 	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		sprintf(tmp,"rec_data %d blocked", bcs->channel);
-		debugl1(cs, tmp);
+		debugl1(cs,"rec_data %d blocked", bcs->channel);
X 		restore_flags(flags);
X 		return;
X 	}
@@ -445,11 +440,9 @@
X 	f2 = ReadReg(cs, HFCD_DATA, cip);
X 	sti();
X 	if (f1 != f2) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d f1(%d) f2(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
X 				bcs->channel, f1, f2);
-			debugl1(cs, tmp);
-		}
X 		cli();
X 		z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
X 		z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
@@ -458,11 +451,9 @@
X 		if (rcnt < 0)
X 			rcnt += cs->hw.hfcD.bfifosize;
X 		rcnt++;
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
X 				bcs->channel, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
X 		if ((skb = hfc_empty_fifo(bcs, rcnt))) {
X 			cli();
X 			skb_queue_tail(&bcs->rqueue, skb);
@@ -490,12 +481,9 @@
X {
X 	struct IsdnCardState *cs = bcs->cs;
X 
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "HFCD bchannel mode %d bchan %d/%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "HFCD bchannel mode %d bchan %d/%d",
X 			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
X 	bcs->mode = mode;
X 	bcs->channel = bc;
X 	switch (mode) {
@@ -543,122 +531,99 @@
X 	long flags;
X 
X 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
X 			save_flags(flags);
X 			cli();
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
X 				skb_queue_tail(&st->l1.bcs->squeue, skb);
X 				restore_flags(flags);
X 			} else {
-				st->l1.bcs->hw.hfc.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
X /*				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
X */				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 				restore_flags(flags);
X 			}
X 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
X 				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
X 				break;
X 			}
X 			save_flags(flags);
X 			cli();
X /*			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-*/			st->l1.bcs->hw.hfc.tx_skb = skb;
+*/			st->l1.bcs->tx_skb = skb;
X 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 			restore_flags(flags);
X 			break;
-		case (PH_PULL_REQ):
-			if (!st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
X 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
X 			} else
X 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
X 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_2bs0(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
X 	}
X }
X 
X void
X close_2bs0(struct BCState *bcs)
X {
-	struct sk_buff *skb;
-
-	mode_2bs0(bcs, 0, 0);
+	mode_2bs0(bcs, 0, bcs->channel);
X 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-		if (bcs->hw.hfc.tx_skb) {
-			dev_kfree_skb(bcs->hw.hfc.tx_skb);
-			bcs->hw.hfc.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
X 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 		}
X 	}
X }
X 
X static int
-open_hfcstate(struct IsdnCardState *cs,
-	      int bc)
+open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
X {
-	struct BCState *bcs = cs->bcs + bc;
-
X 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
X 		skb_queue_head_init(&bcs->rqueue);
X 		skb_queue_head_init(&bcs->squeue);
X 	}
-	bcs->hw.hfc.tx_skb = NULL;
+	bcs->tx_skb = NULL;
X 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 	bcs->event = 0;
X 	bcs->tx_cnt = 0;
X 	return (0);
X }
X 
-static void
-hfc_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				mode_2bs0(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
X int
X setstack_2b(struct PStack *st, struct BCState *bcs)
X {
-	if (open_hfcstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+	if (open_hfcstate(st->l1.hardware, bcs))
X 		return (-1);
X 	st->l1.bcs = bcs;
X 	st->l2.l2l1 = hfc_l2l1;
-	st->ma.manl1 = hfc_manl1;
X 	setstack_manager(st);
X 	bcs->st = st;
+	setstack_l1_B(st);
X 	return (0);
X }
X 
X static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
-
-static void
X hfcd_bh(struct IsdnCardState *cs)
X {
X /*	struct PStack *stptr;
@@ -671,7 +636,7 @@
X 			debugl1(cs, "D-Channel Busy cleared");
X 		stptr = cs->stlist;
X 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
X 			stptr = stptr->next;
X 		}
X 	}
@@ -679,19 +644,19 @@
X 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
X 		switch (cs->ph_state) {
X 			case (0):
-				manl1_msg(cs, PH_RESET_IND, NULL);
+				l1_msg(cs, HW_RESET | INDICATION, NULL);
X 				break;
X 			case (3):
-				manl1_msg(cs, PH_DEACT_IND, NULL);
+				l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
X 				break;
X 			case (8):
-				manl1_msg(cs, PH_RSYNC_IND, NULL);
+				l1_msg(cs, HW_RSYNC | INDICATION, NULL);
X 				break;
X 			case (6):
-				manl1_msg(cs, PH_INFO2_IND, NULL);
+				l1_msg(cs, HW_INFO2 | INDICATION, NULL);
X 				break;
X 			case (7):
-				manl1_msg(cs, PH_I4_P8_IND, NULL);
+				l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
X 				break;
X 			default:
X 				break;
@@ -722,7 +687,6 @@
X 	int chksum;
X 	int count=5;
X 	u_char *ptr;
-	char tmp[64];
X 
X 	save_flags(flags);
X 	cli();
@@ -745,11 +709,9 @@
X 		if (rcnt < 0)
X 			rcnt += cs->hw.hfcD.dfifosize;
X 		rcnt++;
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
X 				f1, f2, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
X 		sti();
X 		idx = 0;
X 		cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;
@@ -796,11 +758,9 @@
X 				WaitNoBusy(cs);
X 				stat = ReadReg(cs, HFCD_DATA, cip);
X 				sti();
-				if (cs->debug & L1_DEB_ISAC) {
-					sprintf(tmp, "empty_dfifo chksum %x stat %x",
+				if (cs->debug & L1_DEB_ISAC)
+					debugl1(cs, "empty_dfifo chksum %x stat %x",
X 						chksum, stat);
-					debugl1(cs, tmp);
-				}
X 				if (stat) {
X 					debugl1(cs, "FIFO CRC error");
X 					dev_kfree_skb(skb);
@@ -837,7 +797,6 @@
X 	int idx, fcnt;
X 	int count;
X 	u_char cip;
-	char tmp[64];
X 
X 	if (!cs->tx_skb)
X 		return;
@@ -855,12 +814,10 @@
X 	cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
X 	cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);
X 	sti();
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
X 			cs->hw.hfcD.f1, cs->hw.hfcD.f2,
X 			cs->hw.hfcD.send[cs->hw.hfcD.f1]);
-		debugl1(cs, tmp);
-	}
X 	fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2;
X 	if (fcnt < 0)
X 		fcnt += 16;
@@ -871,11 +828,9 @@
X 		return;
X 	}
X 	count = GetFreeFifoBytes_D(cs);
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "hfc_fill_Dfifo count(%d/%d)",
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)",
X 			cs->tx_skb->len, count);
-		debugl1(cs, tmp);
-	}
X 	if (count < cs->tx_skb->len) {
X 		if (cs->debug & L1_DEB_ISAC)
X 			debugl1(cs, "hfc_fill_Dfifo no fifo mem");
@@ -929,24 +884,19 @@
X {
X        	u_char exval;
X        	struct BCState *bcs;
-	char tmp[32];
X 	int count=15;
X 	long flags;
X 
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "HFCD irq %x %s", val,
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCD irq %x %s", val,
X 			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
X 			"locked" : "unlocked");
-		debugl1(cs, tmp);
-	}
X 	val &= cs->hw.hfcD.int_m1;
X 	if (val & 0x40) { /* TE state machine irq */
X 		exval = cs->readisac(cs, HFCD_STATES) & 0xf;
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "ph_state chg %d->%d", cs->ph_state,
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ph_state chg %d->%d", cs->ph_state,
X 				exval);
-			debugl1(cs, tmp);
-		}
X 		cs->ph_state = exval;
X 		sched_event_D(cs, D_L1STATECHANGE);
X 		val &= ~0x40;
@@ -983,23 +933,19 @@
X 				if (cs->debug)
X 					debugl1(cs, "hfcd spurious 0x01 IRQ");
X 			} else {
-				if (bcs->hw.hfc.tx_skb) {
+				if (bcs->tx_skb) {
X 					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
X 						hfc_fill_fifo(bcs);
X 						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						sprintf(tmp,"fill_data %d blocked", bcs->channel);
-						debugl1(cs, tmp);
-					}
+					} else
+						debugl1(cs,"fill_data %d blocked", bcs->channel);
X 				} else {
-					if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
X 						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
X 							hfc_fill_fifo(bcs);
X 							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else {
-							sprintf(tmp,"fill_data %d blocked", bcs->channel);
-							debugl1(cs, tmp);
-						}
+						} else
+							debugl1(cs,"fill_data %d blocked", bcs->channel);
X 					} else {
X 						hfc_sched_event(bcs, B_XMTBUFREADY);
X 					}
@@ -1011,23 +957,19 @@
X 				if (cs->debug)
X 					debugl1(cs, "hfcd spurious 0x02 IRQ");
X 			} else {
-				if (bcs->hw.hfc.tx_skb) {
+				if (bcs->tx_skb) {
X 					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
X 						hfc_fill_fifo(bcs);
X 						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						sprintf(tmp,"fill_data %d blocked", bcs->channel);
-						debugl1(cs, tmp);
-					}
+					} else
+						debugl1(cs,"fill_data %d blocked", bcs->channel);
X 				} else {
-					if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
X 						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
X 							hfc_fill_fifo(bcs);
X 							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else {
-							sprintf(tmp,"fill_data %d blocked", bcs->channel);
-							debugl1(cs, tmp);
-						}
+						} else
+							debugl1(cs,"fill_data %d blocked", bcs->channel);
X 					} else {
X 						hfc_sched_event(bcs, B_XMTBUFREADY);
X 					}
@@ -1042,7 +984,7 @@
X 				del_timer(&cs->dbusytimer);
X 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
X 				sched_event_D(cs, D_CLEARBUSY);
-			if (cs->tx_skb) {
+			if (cs->tx_skb)
X 				if (cs->tx_skb->len) {
X 					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
X 						hfc_fill_dfifo(cs);
@@ -1056,7 +998,6 @@
X 					cs->tx_cnt = 0;
X 					cs->tx_skb = NULL;
X 				}
-			}
X 			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
X 				cs->tx_cnt = 0;
X 				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
@@ -1072,10 +1013,8 @@
X 		if (cs->hw.hfcD.int_s1 && count--) {
X 			val = cs->hw.hfcD.int_s1;
X 			cs->hw.hfcD.int_s1 = 0;
-			if (cs->debug & L1_DEB_ISAC) {
-				sprintf(tmp, "HFCD irq %x loop %d", val, 15-count);
-				debugl1(cs, tmp);
-			}
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "HFCD irq %x loop %d", val, 15-count);
X 		} else
X 			val = 0;
X 		restore_flags(flags);
@@ -1083,13 +1022,17 @@
X }
X 
X static void
-HFCD_l2l1(struct PStack *st, int pr, void *arg)
+HFCD_l1hw(struct PStack *st, int pr, void *arg)
X {
X 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
X 	struct sk_buff *skb = arg;
-	char str[64];
+	
X 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
X 			if (cs->tx_skb) {
X 				skb_queue_tail(&cs->sq, skb);
X #ifdef L2FRAME_DEBUG		/* psa */
@@ -1097,12 +1040,6 @@
X 					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
X #endif
X 			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data + 4, skb->len - 4,
-						  str);
-				}
X 				cs->tx_skb = skb;
X 				cs->tx_cnt = 0;
X #ifdef L2FRAME_DEBUG		/* psa */
@@ -1117,19 +1054,17 @@
X 
X 			}
X 			break;
-		case (PH_PULL_IND):
+		case (PH_PULL | INDICATION):
X 			if (cs->tx_skb) {
X 				if (cs->debug & L1_DEB_WARN)
X 					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
X 				skb_queue_tail(&cs->sq, skb);
X 				break;
X 			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
+			if (cs->debug & DEB_DLOG_HEX)
X 				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
X 			cs->tx_skb = skb;
X 			cs->tx_cnt = 0;
X #ifdef L2FRAME_DEBUG		/* psa */
@@ -1142,47 +1077,39 @@
X 			} else
X 				debugl1(cs, "hfc_fill_dfifo blocked");
X 			break;
-		case (PH_PULL_REQ):
+		case (PH_PULL | REQUEST):
X #ifdef L2FRAME_DEBUG		/* psa */
X 			if (cs->debug & L1_DEB_LAPD)
X 				debugl1(cs, "-> PH_REQUEST_PULL");
X #endif
X 			if (!cs->tx_skb) {
X 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
X 			} else
X 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
X 			break;
-	}
-}
-
-void
-hfcd_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	char tmp[32];
-	switch(msg) {
-		case PH_RESET_REQ:
+		case (HW_RESET | REQUEST):
X 			cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
X 			udelay(6);
X 			cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */
X 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
X 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
X 			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
X 			break;
-		case PH_ENABLE_REQ:
+		case (HW_ENABLE | REQUEST):
X 			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
X 			break;
-		case PH_DEACT_ACK:
+		case (HW_DEACTIVATE | REQUEST):
X 			cs->hw.hfcD.mst_m &= ~HFCD_MASTER;
X 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
X 			break;
-		case PH_INFO3_REQ:
+		case (HW_INFO3 | REQUEST):
X 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
X 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
X 			break;
X #if 0
-		case PH_TESTLOOP_REQ:
+		case (HW_TESTLOOP | REQUEST):
X 			u_char val = 0;
X 			if (1 & (int) arg)
X 				val |= 0x0c;
@@ -1208,10 +1135,8 @@
X 			break;
X #endif
X 		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "hfcd_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
-			}
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
X 			break;
X 	}
X }
@@ -1219,7 +1144,7 @@
X void
X setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
X {
-	st->l2.l2l1 = HFCD_l2l1;
+	st->l1.l1hw = HFCD_l1hw;
X }
X 
X static void
@@ -1234,7 +1159,7 @@
X 		stptr = cs->stlist;
X 		
X 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
X 			stptr = stptr->next;
X 		}
X 	}
@@ -1260,7 +1185,6 @@
X init2bds0(struct IsdnCardState *cs))
X {
X 	cs->setstack_d = setstack_hfcd;
-	cs->l1cmd = hfcd_l1cmd;
X 	cs->dbusytimer.function = (void *) hfc_dbusy_timer;
X 	cs->dbusytimer.data = (long) cs;
X 	init_timer(&cs->dbusytimer);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c
--- v2.3.3/linux/drivers/isdn/hisax/hfc_2bs0.c	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/hfc_2bs0.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,24 @@
-/* $Id: hfc_2bs0.c,v 1.4 1998/02/12 23:07:29 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.8 1998/11/15 23:54:43 keil Exp $
X 
X  *  specific routines for CCD's HFC 2BS0
X  *
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *
X  *
X  * $Log: hfc_2bs0.c,v $
+ * Revision 1.8  1998/11/15 23:54:43  keil
+ * changes from 2.0
+ *
+ * Revision 1.7  1998/09/30 22:24:46  keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6  1998/08/13 23:36:28  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5 1998/05/25 12:57:54 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X * Revision 1.4 1998/02/12 23:07:29 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -109,7 +122,6 @@
X 	int idx, cnt;
X 	int rcnt, z1, z2;
X 	u_char cip, f1, f2;
-	char tmp[64];
X 
X 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
X 		debugl1(cs, "hfc_clear_fifo");
@@ -129,21 +141,17 @@
X 	z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
X 	cnt = 32;
X 	while (((f1 != f2) || (z1 != z2)) && cnt--) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc clear %d f1(%d) f2(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc clear %d f1(%d) f2(%d)",
X 				bcs->channel, f1, f2);
-			debugl1(cs, tmp);
-		}
X 		rcnt = z1 - z2;
X 		if (rcnt < 0)
X 			rcnt += cs->hw.hfc.fifosize;
X 		if (rcnt)
X 			rcnt++;
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
X 				bcs->channel, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
X 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
X 		idx = 0;
X 		while ((idx < rcnt) && WaitNoBusy(cs)) {
@@ -180,7 +188,6 @@
X 	int idx;
X 	int chksum;
X 	u_char stat, cip;
-	char tmp[64];
X 
X 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
X 		debugl1(cs, "hfc_empty_fifo");
@@ -235,11 +242,9 @@
X 		chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
X 		WaitNoBusy(cs);
X 		stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
X 				bcs->channel, chksum, stat);
-			debugl1(cs, tmp);
-		}
X 		if (stat) {
X 			debugl1(cs, "FIFO CRC error");
X 			dev_kfree_skb(skb);
@@ -261,11 +266,10 @@
X 	int idx, fcnt;
X 	int count;
X 	u_char cip;
-	char tmp[64];
X 
-	if (!bcs->hw.hfc.tx_skb)
+	if (!bcs->tx_skb)
X 		return;
-	if (bcs->hw.hfc.tx_skb->len <= 0)
+	if (bcs->tx_skb->len <= 0)
X 		return;
X 
X 	save_flags(flags);
@@ -281,12 +285,10 @@
X 	WaitNoBusy(cs);
X 	bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
X 	bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
X 			bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
X 			bcs->hw.hfc.send[bcs->hw.hfc.f1]);
-		debugl1(cs, tmp);
-	}
X 	fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
X 	if (fcnt < 0)
X 		fcnt += 32;
@@ -297,13 +299,11 @@
X 		return;
X 	}
X 	count = GetFreeFifoBytes(bcs);
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d count(%d/%d)",
-			bcs->channel, bcs->hw.hfc.tx_skb->len,
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d count(%ld/%d)",
+			bcs->channel, bcs->tx_skb->len,
X 			count);
-		debugl1(cs, tmp);
-	}
-	if (count < bcs->hw.hfc.tx_skb->len) {
+	if (count < bcs->tx_skb->len) {
X 		if (cs->debug & L1_DEB_HSCX)
X 			debugl1(cs, "hfc_fill_fifo no fifo mem");
X 		restore_flags(flags);
@@ -311,18 +311,18 @@
X 	}
X 	cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
X 	idx = 0;
-	while ((idx < bcs->hw.hfc.tx_skb->len) && WaitNoBusy(cs))
-		cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]);
-	if (idx != bcs->hw.hfc.tx_skb->len) {
+	while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
+		cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+	if (idx != bcs->tx_skb->len) {
X 		debugl1(cs, "FIFO Send BUSY error");
X 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
X 	} else {
-		count =  bcs->hw.hfc.tx_skb->len;
+		count =  bcs->tx_skb->len;
X 		bcs->tx_cnt -= count;
-		if (PACKET_NOACK == bcs->hw.hfc.tx_skb->pkt_type)
+		if (PACKET_NOACK == bcs->tx_skb->pkt_type)
X 			count = -1;
-		dev_kfree_skb(bcs->hw.hfc.tx_skb);
-		bcs->hw.hfc.tx_skb = NULL;
+		dev_kfree_skb(bcs->tx_skb);
+		bcs->tx_skb = NULL;
X 		WaitForBusy(cs);
X 		WaitNoBusy(cs);
X 		cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
@@ -343,7 +343,6 @@
X 	u_char f1, f2, cip;
X 	int receive, transmit, count = 5;
X 	struct sk_buff *skb;
-	char tmp[64];
X 
X 	save_flags(flags);
X       Begin:
@@ -360,11 +359,9 @@
X 	WaitNoBusy(cs);
X 	f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
X 	if (f1 != f2) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d f1(%d) f2(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
X 				bcs->channel, f1, f2);
-			debugl1(cs, tmp);
-		}
X 		WaitForBusy(cs);
X 		z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
X 		z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
@@ -372,11 +369,9 @@
X 		if (rcnt < 0)
X 			rcnt += cs->hw.hfc.fifosize;
X 		rcnt++;
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
X 				bcs->channel, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
X /*              sti(); */
X 		if ((skb = hfc_empty_fifo(bcs, rcnt))) {
X 			skb_queue_tail(&bcs->rqueue, skb);
@@ -388,14 +383,14 @@
X 	restore_flags(flags);
X 	udelay(1);
X 	cli();
-	if (bcs->hw.hfc.tx_skb) {
+	if (bcs->tx_skb) {
X 		transmit = 1;
X 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
X 		hfc_fill_fifo(bcs);
X 		if (test_bit(BC_FLG_BUSY, &bcs->Flag))
X 			transmit = 0;
X 	} else {
-		if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
X 			transmit = 1;
X 			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
X 			hfc_fill_fifo(bcs);
@@ -417,13 +412,11 @@
X {
X 	struct IsdnCardState *cs = bcs->cs;
X 
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "HFC 2BS0 mode %d bchan %d/%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d",
X 			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
X 	bcs->mode = mode;
+	bcs->channel = bc;
X 
X 	switch (mode) {
X 		case (L1_MODE_NULL):
@@ -468,57 +461,66 @@
X 	long flags;
X 
X 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
X 			save_flags(flags);
X 			cli();
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
X 				skb_queue_tail(&st->l1.bcs->squeue, skb);
X 				restore_flags(flags);
X 			} else {
-				st->l1.bcs->hw.hfc.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
X 				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
X 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 				restore_flags(flags);
X 			}
X 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
X 				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
X 				break;
X 			}
X 			save_flags(flags);
X 			cli();
X 			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->hw.hfc.tx_skb = skb;
+			st->l1.bcs->tx_skb = skb;
X 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 			restore_flags(flags);
X 			break;
-		case (PH_PULL_REQ):
-			if (!st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
X 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
X 			} else
X 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
X 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_hfc(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
X 	}
X }
X 
+
X void
X close_hfcstate(struct BCState *bcs)
X {
-	struct sk_buff *skb;
-
-	mode_hfc(bcs, 0, 0);
+	mode_hfc(bcs, 0, bcs->channel);
X 	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-		if (bcs->hw.hfc.tx_skb) {
-			dev_kfree_skb(bcs->hw.hfc.tx_skb);
-			bcs->hw.hfc.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
X 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 		}
X 	}
@@ -526,50 +528,30 @@
X }
X 
X static int
-open_hfcstate(struct IsdnCardState *cs,
-	      int bc)
+open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
X {
-	struct BCState *bcs = cs->bcs + bc;
-
X 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
X 		skb_queue_head_init(&bcs->rqueue);
X 		skb_queue_head_init(&bcs->squeue);
X 	}
-	bcs->hw.hfc.tx_skb = NULL;
+	bcs->tx_skb = NULL;
X 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 	bcs->event = 0;
X 	bcs->tx_cnt = 0;
X 	return (0);
X }
X 
-static void
-hfc_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				mode_hfc(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
X int
X setstack_hfc(struct PStack *st, struct BCState *bcs)
X {
-	if (open_hfcstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+	if (open_hfcstate(st->l1.hardware, bcs))
X 		return (-1);
X 	st->l1.bcs = bcs;
X 	st->l2.l2l1 = hfc_l2l1;
-	st->ma.manl1 = hfc_manl1;
X 	setstack_manager(st);
X 	bcs->st = st;
+	setstack_l1_B(st);
X 	return (0);
X }
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- v2.3.3/linux/drivers/isdn/hisax/hisax.h	Mon Mar 15 16:11:30 1999
+++ linux/drivers/isdn/hisax/hisax.h	Sun May 23 10:03:41 1999
@@ -1,8 +1,48 @@
-/* $Id: hisax.h,v 2.14 1998/02/11 17:28:04 keil Exp $
+/* $Id: hisax.h,v 2.26 1998/11/15 23:54:45 keil Exp $
X 
X  *   Basic declarations, defines and prototypes
X  *
X  * $Log: hisax.h,v $
+ * Revision 2.26  1998/11/15 23:54:45  keil
+ * changes from 2.0
+ *
+ * Revision 2.25  1998/09/30 22:28:42  keil
+ * More work for ISAR support
+ *
+ * Revision 2.24  1998/08/20 13:50:39  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.23  1998/08/13 23:36:31  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.22 1998/07/15 15:01:28 calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.21 1998/05/25 14:10:05 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.20 1998/05/25 12:57:57 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.19 1998/04/15 16:39:15 keil
+ * Add S0Box and Teles PCI support
+ *
+ * Revision 2.18  1998/03/26 07:10:04  paul
+ * The jumpmatrix table in struct Fsm was an array of "int". This is not
+ * large enough for pointers to functions on Linux/Alpha (instant crash
+ * on "insmod hisax). Now there is a typedef for the pointer to function.
+ * This also prevents warnings about "incompatible pointer types".
+ *
+ * Revision 2.17  1998/03/19 13:18:43  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 2.16  1998/03/09 23:19:25  keil
+ * Changes for PCMCIA
+ *
X * Revision 2.14 1998/02/11 17:28:04 keil
X  * Niccy PnP/PCI support
X  *
@@ -72,120 +112,90 @@
X #include <linux/isdnif.h>
X #include <linux/tty.h>
X #include <linux/init.h>
+#include <linux/serialP.h>
+
+#define REQUEST		0
+#define CONFIRM		1
+#define INDICATION	2
+#define RESPONSE	3
+
+#define HW_ENABLE	0x0000
+#define HW_RESET	0x0004
+#define HW_POWERUP	0x0008
+#define HW_ACTIVATE	0x0010
+#define HW_DEACTIVATE	0x0018
+#define HW_INFO2	0x0020
+#define HW_INFO3	0x0030
+#define HW_INFO4_P8	0x0040
+#define HW_INFO4_P10	0x0048
+#define HW_RSYNC	0x0060
+#define HW_TESTLOOP	0x0070
+#define CARD_RESET	0x00F0
+#define CARD_SETIRQ	0x00F1
+#define CARD_INIT	0x00F2
+#define CARD_RELEASE	0x00F3
+#define CARD_TEST	0x00F4
+#define CARD_AUX_IND	0x00F5
+#define CARD_LOAD_FIRM	0x00F6
+
+#define PH_ACTIVATE	0x0100
+#define PH_DEACTIVATE	0x0110
+#define PH_DATA		0x0120
+#define PH_PULL		0x0130
+#define PH_TESTLOOP	0x0140
+#define PH_PAUSE	0x0150
+#define MPH_ACTIVATE	0x0180
+#define MPH_DEACTIVATE	0x0190
+#define MPH_INFORMATION	0x01A0
+
+#define DL_ESTABLISH	0x0200
+#define DL_RELEASE	0x0210
+#define DL_DATA		0x0220
+#define DL_FLUSH	0x0224
+#define DL_UNIT_DATA	0x0230
+#define MDL_ASSIGN	0x0280
+#define MDL_REMOVE	0x0284
+#define MDL_ERROR	0x0288
+#define MDL_INFO_SETUP	0x02E0
+#define MDL_INFO_CONN	0x02E4
+#define MDL_INFO_REL	0x02E8
+
+#define CC_SETUP	0x0300
+#define CC_RESUME	0x0304
+#define CC_MORE_INFO	0x0310
+#define CC_IGNORE	0x0320
+#define CC_REJECT	0x0324
+#define CC_SETUP_COMPL	0x0330
+#define CC_PROCEEDING	0x0340
+#define CC_ALERTING	0x0344
+#define CC_CONNECT	0x0350
+#define CC_CHARGE	0x0354
+#define CC_DISCONNECT	0x0360
+#define CC_RELEASE	0x0368
+#define CC_SUSPEND	0x0370
+#define CC_T303		0x0383
+#define CC_T304		0x0384
+#define CC_T305		0x0385
+#define CC_T308_1	0x0388
+#define CC_T308_2	0x0389
+#define CC_T310		0x0390
+#define CC_T313		0x0393
+#define CC_T318		0x0398
+#define CC_T319		0x0399
+#define CC_NOSETUP_RSP	0x03E0
+#define CC_SETUP_ERR	0x03E1
+#define CC_SUSPEND_ERR	0x03E2
+#define CC_RESUME_ERR	0x03E3
+#define CC_CONNECT_ERR	0x03E4
+#define CC_RELEASE_ERR	0x03E5
+#define CC_DLRL		0x03F0
+#define CC_RESTART	0x03F4
X 
-#define PH_ACTIVATE_REQ	0x0010
-#define PH_ACTIVATE_CNF	0x0011
-#define PH_ACTIVATE_IND	0x0012
-#define PH_DEACTIVATE_REQ 0x0020
-#define PH_DEACTIVATE_CNF 0x0021
-#define PH_DEACTIVATE_IND 0x0022
-#define PH_DEACT_REQ	0x0024
-#define PH_DEACT_CNF	0x0025
-#define PH_DEACT_IND	0x0026
-#define PH_DEACT_ACK	0x0027
-#define PH_TESTLOOP_REQ	0x0030
-#define PH_PAUSE_CNF	0x0035
-#define PH_PAUSE_IND	0x0036
-#define PH_PULL_REQ	0x0038
-#define PH_PULL_CNF	0x0039
-#define	PH_PULL_IND	0x003A
-#define PH_DATA_REQ	0x0040
-#define PH_DATA_IND	0x0042
-
-#define PH_INFO3_REQ	0x0008
-#define PH_INFO2_IND	0x000A
-#define PH_ENABLE_REQ	0x0004
-#define PH_RSYNC_IND	0x0006
-#define PH_RESET_REQ	0x0000
-#define PH_RESET_IND	0x0002
-#define PH_POWERUP_CNF	0x0003
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 20'
echo 'File patch-2.3.4 is continued in part 21'
echo 21 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 21 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
-#define PH_ACTIV_REQ	0x000C
-#define PH_I4_P8_IND	0x000D
-#define PH_I4_P10_IND	0x000F
-
-#define MDL_ASSIGN_REQ	0x0050
-#define MDL_ASSIGN_IND	0x0052
-#define MDL_REMOVE_REQ	0x0054
-#define MDL_ERROR_REQ	0x0058
-#define MDL_ERROR_IND	0x005A
-#define CARD_AUX_IND	0x005E
-
-#define DL_UNIT_DATA	6
-#define CC_ESTABLISH	7
-#define DL_ESTABLISH	8
-#define DL_DATA		9
-
-#define CC_CONNECT	15
-#define DL_RELEASE	20
-#define DL_FLUSH	21
-
-#define CC_REJECT	23
-
-#define CC_SETUP_REQ	24
-#define CC_SETUP_CNF	25
-#define CC_SETUP_IND	26
-#define CC_SETUP_RSP	27
-#define CC_SETUP_COMPLETE_IND	28
-
-#define CC_DISCONNECT_REQ	29
-#define CC_DISCONNECT_IND	30
-
-#define CC_RELEASE_CNF	31
-#define CC_RELEASE_IND	32
-#define CC_RELEASE_REQ	33
-
-#define CC_REJECT_REQ	34
-
-#define CC_PROCEEDING_IND	35
-
-#define CC_DLRL		36
-#define CC_DLEST	37
-
-#define CC_ALERTING_REQ	38
-#define CC_ALERTING_IND	39
-
-#define DL_STOP		40
-#define DL_START	41
-
-#define MDL_INFO_SETUP	42
-#define MDL_INFO_CONN	43
-#define MDL_INFO_REL	44
-#define MDL_NOTEIPROC	46
-
-#define LC_ESTABLISH	47
-#define LC_RELEASE	48
-
-#define CC_INFO_CHARGE	52
-
-#define CC_MORE_INFO	53
-#define CC_IGNORE	54
-#define CC_RESTART	55
-
-
-#define CC_T303		60
-#define CC_T304		61
-#define CC_T305		62
-#define CC_T308_1	64
-#define CC_T308_2	65
-#define CC_T310		66
-#define CC_T313		67
-#define CC_T318		68
-#define CC_T319		69
-
-#define CC_NOSETUP_RSP_ERR	70
-#define CC_SETUP_ERR		71
-#define CC_CONNECT_ERR		72
-#define CC_RELEASE_ERR		73
-
-#define CARD_RESET	0x1001
-#define CARD_SETIRQ	0x1002
-#define CARD_INIT	0x1003
-#define CARD_RELEASE	0x1004
-#define CARD_TEST	0x1005
X 
X #ifdef __KERNEL__
X 
X #define MAX_DFRAME_LEN	260
+#define MAX_DFRAME_LEN_L1	300
X #define HSCX_BUFMAX	4096
X #define MAX_DATA_SIZE	(HSCX_BUFMAX - 4)
X #define MAX_DATA_MEM	(HSCX_BUFMAX + 64)
@@ -193,6 +203,8 @@
X #define MAX_HEADER_LEN	4
X #define MAX_WINDOW	8
X #define MAX_MON_FRAME	32
+#define MAX_DLOG_SPACE	2048
+#define MAX_BLOG_SPACE	256
X 
X /* #define I4L_IRQ_FLAG SA_INTERRUPT */
X #define I4L_IRQ_FLAG    0
@@ -201,8 +213,12 @@
X  * Statemachine
X  */
X 
+struct FsmInst;
+
+typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
+
X struct Fsm {
-	int *jumpmatrix;
+	FSMFNPTR *jumpmatrix;
X 	int state_count, event_count;
X 	char **strEvent, **strState;
X };
@@ -213,7 +229,7 @@
X 	int debug;
X 	void *userdata;
X 	int userint;
-	void (*printdebug) (struct FsmInst *, char *);
+	void (*printdebug) (struct FsmInst *, char *, ...);
X };
X 
X struct FsmNode {
@@ -249,9 +265,10 @@
X 	struct FsmInst l1m;
X 	struct FsmTimer	timer;
X 	void (*l1l2) (struct PStack *, int, void *);
-	void (*l1man) (struct PStack *, int, void *);
+	void (*l1hw) (struct PStack *, int, void *);
X 	void (*l1tei) (struct PStack *, int, void *);
X 	int mode, bc;
+	int delay;
X };
X 
X #define GROUP_TEI	127
@@ -266,17 +283,20 @@
X #define FLG_ORIG	2
X #define FLG_MOD128	3
X #define FLG_PEND_REL	4
-#define FLG_L3_INIT	5 
-#define FLG_T200_RUN	6 
+#define FLG_L3_INIT	5
+#define FLG_T200_RUN	6
X #define FLG_ACK_PEND	7
X #define FLG_REJEXC	8
X #define FLG_OWN_BUSY	9
X #define FLG_PEER_BUSY	10
X #define FLG_DCHAN_BUSY	11
+#define FLG_L1_ACTIV	12
+#define FLG_ESTAB_PEND	13
+#define FLG_PTP		14
+#define FLG_FIXED_TEI	15
X 
X struct Layer2 {
X 	int tei;
-	int tei_wanted;
X 	int sap;
X 	int maxlen;
X 	unsigned int flag;
@@ -288,23 +308,25 @@
X 	struct sk_buff_head i_queue;
X 	struct sk_buff_head ui_queue;
X 	void (*l2l1) (struct PStack *, int, void *);
-	void (*l2man) (struct PStack *, int, void *);
X 	void (*l2l3) (struct PStack *, int, void *);
X 	void (*l2tei) (struct PStack *, int, void *);
X 	struct FsmInst l2m;
X 	struct FsmTimer t200, t203;
X 	int T200, N200, T203;
X 	int debug;
-	char debug_id[32];
+	char debug_id[16];
X };
X 
X struct Layer3 {
-	void (*l3l4) (struct l3_process *, int, void *);
+	void (*l3l4) (struct PStack *, int, void *);
X 	void (*l3l2) (struct PStack *, int, void *);
+	struct FsmInst l3m;
+	struct sk_buff_head squeue;
X 	struct l3_process *proc;
X 	struct l3_process *global;
X 	int N303;
X 	int debug;
+	char debug_id[8];
X };
X 
X struct LLInterface {
@@ -321,8 +343,6 @@
X 	struct FsmTimer t202;
X 	int T202, N202, debug;
X 	void (*layer) (struct PStack *, int, void *);
-	void (*manl1) (struct PStack *, int, void *);
-	void (*manl2) (struct PStack *, int, void *);
X };
X 
X 
@@ -343,7 +363,7 @@
X 	struct Layer1 l1;
X 	struct Layer2 l2;
X 	struct Layer3 l3;
-	struct LLInterface lli; 
+	struct LLInterface lli;
X 	struct Management ma;
X 	int protocol;		/* EDSS1 or 1TR6 */
X };
@@ -361,21 +381,55 @@
X };
X 
X struct hscx_hw {
+	int hscx;
+	int rcvidx;
+	int count;              /* Current skb sent count */
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+};
+
+struct isar_reg {
+	unsigned int Flags;
+	volatile u_char bstat;
+	volatile u_char iis;
+	volatile u_char cmsb;
+	volatile u_char clsb;
+	volatile u_char par[8];
+};
+
+struct isar_hw {
+	int dpath;
+	int rcvidx;
+	int txcnt;
+	int mml;
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	struct isar_reg *reg;
+};
+
+struct hdlc_stat_reg {
+	u_char cmd  __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char fill __attribute__((packed));
+};
+
+struct hdlc_hw {
+	union {
+		u_int ctrl;
+		struct hdlc_stat_reg sr;
+	} ctrl;
+	u_int stat;
X 	int rcvidx;
X 	int count;              /* Current skb sent count */
X 	u_char *rcvbuf;         /* B-Channel receive Buffer */
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
X };
X 
X struct hfcB_hw {
X 	unsigned int *send;
X 	int f1;
X 	int f2;
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
X };
X 
X struct tiger_hw {
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
X 	u_int *send;
X 	u_int *s_irq;
X 	u_int *s_end;
@@ -397,8 +451,7 @@
X 	u_char s_state;
X };
X 
-struct foreign_hw {
-	int doHDLCprocessing;
+struct amd7930_hw {
X 	u_char *tx_buff;
X 	u_char *rv_buff;
X 	int rv_buff_in;
@@ -407,9 +460,9 @@
X 	struct hdlc_state *hdlc_state;
X 	struct tq_struct tq_rcv;
X 	struct tq_struct tq_xmt;
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
X };
X 
+
X #define BC_FLG_INIT	1
X #define BC_FLG_ACTIV	2
X #define BC_FLG_BUSY	3
@@ -420,6 +473,7 @@
X #define L1_MODE_NULL	0
X #define L1_MODE_TRANS	1
X #define L1_MODE_HDLC	2
+#define L1_MODE_MODEM	7
X 
X struct BCState {
X 	int channel;
@@ -427,34 +481,26 @@
X 	int Flag;
X 	struct IsdnCardState *cs;
X 	int tx_cnt;		/* B-Channel transmit counter */
+	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
X 	struct sk_buff_head rqueue;	/* B-Channel receive Queue */
X 	struct sk_buff_head squeue;	/* B-Channel send Queue */
X 	struct PStack *st;
+	u_char *blog;
+	struct timer_list transbusy;
X 	struct tq_struct tqueue;
X 	int event;
X 	int  (*BC_SetStack) (struct PStack *, struct BCState *);
X 	void (*BC_Close) (struct BCState *);
X 	union {
X 		struct hscx_hw hscx;
+		struct hdlc_hw hdlc;
+		struct isar_hw isar;
X 		struct hfcB_hw hfc;
X 		struct tiger_hw tiger;
-		struct foreign_hw foreign;
+		struct amd7930_hw  amd7930;
X 	} hw;
X };
X 
-struct LcFsm {
-	int type;
-	int delay;
-	struct FsmInst lcfi;
-	struct Channel *ch;
-	void (*lccall) (struct LcFsm *, int, void *);
-	struct PStack *st;
-	int l2_establish;
-	int l2_start;
-	struct FsmTimer act_timer;
-	char debug_id[32];
-};
-
X struct Channel {
X 	struct PStack *b_st, *d_st;
X 	struct IsdnCardState *cs;
@@ -462,11 +508,10 @@
X 	int chan;
X 	int incoming;
X 	struct FsmInst fi;
-	struct LcFsm *lc_d;
-	struct LcFsm *lc_b;
X 	struct FsmTimer drel_timer, dial_timer;
X 	int debug;
X 	int l2_protocol, l2_active_protocol;
+	int l3_protocol;
X 	int data_open;
X 	struct l3_process *proc;
X 	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
@@ -487,21 +532,33 @@
X 	unsigned int counter;
X 	unsigned int status;
X 	struct timer_list tl;
+	unsigned int MFlag;
+	struct BCState *bcs;
+	u_char *transbuf;
+	u_char *rcvbuf;
+	unsigned int transp;
+	unsigned int rcvp;
+	unsigned int transcnt;
+	unsigned int rcvcnt;
+	u_char IER;
+	u_char FCR;
+	u_char LCR;
+	u_char MCR;
X 	u_char ctrl_reg;
-};	
+};
X 
X struct teles3_hw {
X 	unsigned int cfg_reg;
-	unsigned int isac;
-	unsigned int hscx[2];
-	unsigned int isacfifo;
-	unsigned int hscxfifo[2];
-};	
+	signed   int isac;
+	signed   int hscx[2];
+	signed   int isacfifo;
+	signed   int hscxfifo[2];
+};
X 
X struct teles0_hw {
X 	unsigned int cfg_reg;
X 	unsigned int membase;
-};	
+};
X 
X struct avm_hw {
X 	unsigned int cfg_reg;
@@ -510,7 +567,7 @@
X 	unsigned int isacfifo;
X 	unsigned int hscxfifo[2];
X 	unsigned int counter;
-};	
+};
X 
X struct ix1_hw {
X 	unsigned int cfg_reg;
@@ -530,7 +587,7 @@
X 	unsigned int status;
X 	struct timer_list tl;
X 	u_char ctrl_reg;
-};	
+};
X 
X struct asus_hw {
X 	unsigned int cfg_reg;
@@ -559,6 +616,9 @@
X 	unsigned int hscx;
X 	unsigned int reset_on;
X 	unsigned int reset_off;
+	struct isar_reg isar;
+	unsigned int chip;
+	unsigned int bus;
X };
X 
X struct spt_hw {
@@ -566,7 +626,7 @@
X 	unsigned int isac;
X 	unsigned int hscx[2];
X 	unsigned char res_irq;
-};	
+};
X 
X struct mic_hw {
X 	unsigned int cfg_reg;
@@ -610,6 +670,7 @@
X 
X #define HW_IOM1		0
X #define HW_IPAC		1
+#define HW_ISAR		2
X #define FLG_TWO_DCHAN	4
X #define FLG_L1_DBUSY	5
X #define FLG_DBUSY_TIMER 6
@@ -624,7 +685,7 @@
X 	unsigned char subtyp;
X 	int protocol;
X 	unsigned int irq;
-	int HW_Flags; 
+	int HW_Flags;
X 	int *busy_flag;
X 	union {
X 		struct elsa_hw elsa;
@@ -641,7 +702,6 @@
X 		struct njet_hw njet;
X 		struct hfcD_hw hfcD;
X 		struct ix1_hw niccy;
-                struct foreign_interface *foreign;
X 	} hw;
X 	int myid;
X 	isdn_if iif;
@@ -657,7 +717,6 @@
X 	void   (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char);
X 	void   (*BC_Send_Data) (struct BCState *);
X 	int    (*cardmsg) (struct IsdnCardState *, int, void *);
-	void   (*l1cmd) (struct IsdnCardState *, int, void *);
X 	struct Channel channel[2];
X 	struct BCState bcs[2];
X 	struct PStack *stlist;
@@ -671,8 +730,7 @@
X 	struct sk_buff_head rq, sq; /* D-channel queues */
X 	int ph_state;
X 	int cardnr;
-	int dlogflag;
-	char *dlogspace;
+	char *dlog;
X 	int debug;
X 	u_char *mon_tx;
X 	u_char *mon_rx;
@@ -688,6 +746,8 @@
X #define  MON0_TX	4
X #define  MON1_TX	8
X 
+#define	 HISAX_MAX_CARDS	8
+
X #define  ISDN_CTYPE_16_0	1
X #define  ISDN_CTYPE_8_0		2
X #define  ISDN_CTYPE_16_3	3
@@ -712,9 +772,12 @@
X #define  ISDN_CTYPE_SEDLBAUER_PCMCIA	22
X #define  ISDN_CTYPE_AMD7930	23
X #define  ISDN_CTYPE_NICCY	24
-#define  ISDN_CTYPE_DBRI	25
+#define  ISDN_CTYPE_S0BOX	25
+#define  ISDN_CTYPE_A1_PCMCIA	26
+#define  ISDN_CTYPE_FRITZPCI	27
+#define  ISDN_CTYPE_SEDLBAUER_FAX     28
X 
-#define  ISDN_CTYPE_COUNT	25
+#define  ISDN_CTYPE_COUNT	28
X 
X #ifdef ISDN_CHIP_ISAC
X #undef ISDN_CHIP_ISAC
@@ -742,15 +805,42 @@
X #define  CARD_TELES3  0
X #endif
X 
+#ifdef	CONFIG_HISAX_TELESPCI
+#define  CARD_TELESPCI (1<< ISDN_CTYPE_TELESPCI)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_TELESPCI  0
+#endif
+
X #ifdef	CONFIG_HISAX_AVM_A1
X #define  CARD_AVM_A1 (1<< ISDN_CTYPE_A1)
-#ifndef ISDN_CHIP_ISAC 
+#ifndef ISDN_CHIP_ISAC
X #define ISDN_CHIP_ISAC 1
X #endif
X #else
X #define  CARD_AVM_A1  0
X #endif
X 
+#ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
+#define  CARD_AVM_A1_PCMCIA (1<< ISDN_CTYPE_A1_PCMCIA)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_AVM_A1_PCMCIA  0
+#endif
+
+#ifdef	CONFIG_HISAX_FRITZPCI
+#define  CARD_FRITZPCI (1<< ISDN_CTYPE_FRITZPCI)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_FRITZPCI  0
+#endif
+
X #ifdef	CONFIG_HISAX_ELSA
X #define  CARD_ELSA (1<< ISDN_CTYPE_ELSA) | (1<< ISDN_CTYPE_ELSA_PNP) | \
X 		   (1<< ISDN_CTYPE_ELSA_PCMCIA) | (1<< ISDN_CTYPE_ELSA_PCI)
@@ -803,7 +893,7 @@
X #endif
X 
X #ifdef  CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA)
+#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA) | ( 1 << ISDN_CTYPE_SEDLBAUER_FAX)
X #ifndef ISDN_CHIP_ISAC
X #define ISDN_CHIP_ISAC 1
X #endif
@@ -859,18 +949,21 @@
X #define CARD_NICCY 0
X #endif
X 
-#ifdef  CONFIG_HISAX_DBRI
-#define CARD_DBRI (1 << ISDN_CTYPE_DBRI)
+#ifdef	CONFIG_HISAX_S0BOX
+#define	CARD_S0BOX (1 << ISDN_CTYPE_S0BOX)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
X #else
-#define CARD_DBRI 0
+#define CARD_S0BOX 0
X #endif
X 
-
X #define  SUPORTED_CARDS  (CARD_TELES0 | CARD_TELES3 | CARD_AVM_A1 | CARD_ELSA \
X 			 | CARD_IX1MICROR2 | CARD_DIEHLDIVA | CARD_ASUSCOM \
X 			 | CARD_TELEINT | CARD_SEDLBAUER | CARD_SPORTSTER \
X 			 | CARD_MIC | CARD_NETJET | CARD_TELES3C | CARD_AMD7930 \
-			 | CARD_NICCY | CARD_DBRI)
+			 | CARD_AVM_A1_PCMCIA | CARD_FRITZPCI\
+			 | CARD_NICCY | CARD_S0BOX | CARD_TELESPCI)
X 
X #define TEI_PER_CARD 0
X 
@@ -883,25 +976,38 @@
X #undef TEI_PER_CARD
X #define TEI_PER_CARD 1
X #define HISAX_EURO_SENDCOMPLETE 1
-#ifdef	CONFIG_HISAX_ML
+#define EXT_BEARER_CAPS 1
+#define HISAX_SEND_STD_LLC_IE 1
+#ifdef	CONFIG_HISAX_NO_SENDCOMPLETE
X #undef HISAX_EURO_SENDCOMPLETE
X #endif
+#ifdef	CONFIG_HISAX_NO_LLC
+#undef HISAX_SEND_STD_LLC_IE
+#endif
X #undef HISAX_DE_AOC
X #ifdef CONFIG_DE_AOC
X #define HISAX_DE_AOC 1
X #endif
X #endif
X 
-#if TEI_PER_CARD
-#undef TEI_FIXED
-#endif
+/* L1 Debug */
+#define	L1_DEB_WARN		0x01
+#define	L1_DEB_INTSTAT		0x02
+#define	L1_DEB_ISAC		0x04
+#define	L1_DEB_ISAC_FIFO	0x08
+#define	L1_DEB_HSCX		0x10
+#define	L1_DEB_HSCX_FIFO	0x20
+#define	L1_DEB_LAPD	        0x40
+#define	L1_DEB_IPAC	        0x80
+#define	L1_DEB_RECEIVE_FRAME    0x100
+#define L1_DEB_MONITOR		0x200
+#define DEB_DLOG_HEX		0x400
+#define DEB_DLOG_VERBOSE	0x800
X 
-#undef PTP_DATA_LINK
+#define L2FRAME_DEBUG
X 
-#ifdef PTP_DATA_LINK
-#undef TEI_FIXED
-#define TEI_FIXED 0
-#define LAYER2_WATCHING
+#ifdef L2FRAME_DEBUG
+extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
X #endif
X 
X struct IsdnCard {
@@ -911,17 +1017,26 @@
X 	struct IsdnCardState *cs;
X };
X 
-void setstack_isdnl2(struct PStack *st, char *debug_id);
-int HiSax_inithardware(int *);
-void HiSax_closehardware(void);
+void init_bcstate(struct IsdnCardState *cs, int bc);
X 
X void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs);
X unsigned int random_ri(void);
-void setstack_isdnl3(struct PStack *st, struct Channel *chanp);
X void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st);
+void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
+
+void setstack_l1_B(struct PStack *st);
+
+void setstack_tei(struct PStack *st);
+void setstack_manager(struct PStack *st);
+
+void setstack_isdnl2(struct PStack *st, char *debug_id);
X void releasestack_isdnl2(struct PStack *st);
+void setstack_transl2(struct PStack *st);
+void releasestack_transl2(struct PStack *st);
+
+void setstack_l3dc(struct PStack *st, struct Channel *chanp);
+void setstack_l3bc(struct PStack *st, struct Channel *chanp);
X void releasestack_isdnl3(struct PStack *st);
-void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
X 
X u_char *findie(u_char * p, int size, u_char ie, int wanted_set);
X int getcallref(u_char * p);
@@ -937,20 +1052,18 @@
X void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event,
X 	void *arg, int where);
X void FsmDelTimer(struct FsmTimer *ft, int where);
-void jiftime(char *s, long mark);
+int jiftime(char *s, long mark);
X 
X int HiSax_command(isdn_ctrl * ic);
X int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-void HiSax_putstatus(struct IsdnCardState *csta, char *buf);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
X void HiSax_reportcard(int cardnr);
X int QuickHex(char *txt, u_char * p, int cnt);
-void LogFrame(struct IsdnCardState *sp, u_char * p, int size);
-void dlogframe(struct IsdnCardState *sp, u_char * p, int size, char *comment);
+void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
+void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
X void iecpy(u_char * dest, u_char * iestart, int ieoffset);
-void setstack_transl2(struct PStack *st);
-void releasestack_transl2(struct PStack *st);
-void setstack_tei(struct PStack *st);
-void setstack_manager(struct PStack *st);
+int discard_queue(struct sk_buff_head *q);
X #ifdef ISDN_CHIP_ISAC
X void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
X #endif	/* ISDN_CHIP_ISAC */
@@ -958,18 +1071,21 @@
X 
X #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
X 
-int ll_run(struct IsdnCardState *csta);
-void ll_stop(struct IsdnCardState *csta);
+int ll_run(struct IsdnCardState *cs);
+void ll_stop(struct IsdnCardState *cs);
X void CallcNew(void);
X void CallcFree(void);
-int CallcNewChan(struct IsdnCardState *csta);
-void CallcFreeChan(struct IsdnCardState *csta);
+int CallcNewChan(struct IsdnCardState *cs);
+void CallcFreeChan(struct IsdnCardState *cs);
X void Isdnl1New(void);
X void Isdnl1Free(void);
X void Isdnl2New(void);
X void Isdnl2Free(void);
-void init_tei(struct IsdnCardState *sp, int protocol);
-void release_tei(struct IsdnCardState *sp);
+void Isdnl3New(void);
+void Isdnl3Free(void);
+void init_tei(struct IsdnCardState *cs, int protocol);
+void release_tei(struct IsdnCardState *cs);
X char *HiSax_getrev(const char *revision);
X void TeiNew(void);
X void TeiFree(void);
+int certification_check(int output);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c
--- v2.3.3/linux/drivers/isdn/hisax/hscx.c	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/hscx.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,40 @@
-/* $Id: hscx.c,v 1.7 1998/02/12 23:07:36 keil Exp $
+/* $Id: hscx.c,v 1.16 1998/11/15 23:54:48 keil Exp $
X 
X  * hscx.c   HSCX specific routines
X  *
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *
X  *
X  * $Log: hscx.c,v $
+ * Revision 1.16  1998/11/15 23:54:48  keil
+ * changes from 2.0
+ *
+ * Revision 1.15 1998/08/20 13:50:42 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.14 1998/08/13 23:36:33 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.13  1998/06/26 22:03:28  keil
+ * send flags between hdlc frames
+ *
+ * Revision 1.12  1998/06/09 18:26:01  keil
+ * PH_DEACTIVATE B-channel every time signaled to higher layer
+ *
+ * Revision 1.11  1998/05/25 14:10:07  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 1.10 1998/05/25 12:57:59 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.9 1998/04/15 16:45:33 keil
+ * new init code
+ *
+ * Revision 1.8  1998/03/19 13:16:24  keil
+ * fix the correct release of the hscx
+ *
X  * Revision 1.7  1998/02/12 23:07:36  keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -30,6 +59,7 @@
X #define __NO_VERSION__
X #include "hisax.h"
X #include "hscx.h"
+#include "isac.h"
X #include "isdnl1.h"
X #include <linux/interrupt.h>
X 
@@ -56,21 +86,20 @@
X modehscx(struct BCState *bcs, int mode, int bc)
X {
X 	struct IsdnCardState *cs = bcs->cs;
-	int hscx = bcs->channel;
+	int hscx = bcs->hw.hscx.hscx;
X 
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
- sprintf(tmp, "hscx %c mode %d ichan %d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hscx %c mode %d ichan %d",
X 			'A' + hscx, mode, bc);
-		debugl1(cs, tmp);
-	}
X 	bcs->mode = mode;
- cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, 0x85);
+	bcs->channel = bc;
X 	cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
+	cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+		test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
X 	cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
@@ -90,14 +119,16 @@
X 	}
X 	switch (mode) {
X 		case (L1_MODE_NULL):
-			cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0xff);
-			cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0xff);
+			cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
+			cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
X 			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
X 			break;
X 		case (L1_MODE_TRANS):
X 			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
X 			break;
X 		case (L1_MODE_HDLC):
+			cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+				test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
X 			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
X 			break;
X 	}
@@ -114,89 +145,106 @@
X 	mark_bh(IMMEDIATE_BH);
X }
X 
-static void
+void
X hscx_l2l1(struct PStack *st, int pr, void *arg)
X {
X 	struct sk_buff *skb = arg;
X 	long flags;
X 
X 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
X 			save_flags(flags);
X 			cli();
- if (st->l1.bcs->hw.hscx.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
X 				skb_queue_tail(&st->l1.bcs->squeue, skb);
X 				restore_flags(flags);
X 			} else {
- st->l1.bcs->hw.hscx.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
X 				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
X 				st->l1.bcs->hw.hscx.count = 0;
X 				restore_flags(flags);
X 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 			}
X 			break;
-		case (PH_PULL_IND):
- if (st->l1.bcs->hw.hscx.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
X 				printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
X 				break;
X 			}
X 			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- st->l1.bcs->hw.hscx.tx_skb = skb;
+			st->l1.bcs->tx_skb = skb;
X st->l1.bcs->hw.hscx.count = 0;
X 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 			break;
-		case (PH_PULL_REQ):
- if (!st->l1.bcs->hw.hscx.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
X 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
X 			} else
X 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
X 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ modehscx(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
X 	}
-
X }
X 
X void
X close_hscxstate(struct BCState *bcs)
X {
-	struct sk_buff *skb;
-
- modehscx(bcs, 0, 0);
+	modehscx(bcs, 0, bcs->channel);
X 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
X 		if (bcs->hw.hscx.rcvbuf) {
X 			kfree(bcs->hw.hscx.rcvbuf);
X 			bcs->hw.hscx.rcvbuf = NULL;
X 		}
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
X 		}
-		if (bcs->hw.hscx.tx_skb) {
-			dev_kfree_skb(bcs->hw.hscx.tx_skb);
-			bcs->hw.hscx.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
X 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 		}
X 	}
X }
X 
-static int
-open_hscxstate(struct IsdnCardState *cs,
-	       int bc)
+int
+open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
X {
-	struct BCState *bcs = cs->bcs + bc;
-
X 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
X 		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
X 			printk(KERN_WARNING
-			       "HiSax: No memory for hscx.rcvbuf\n");
+				"HiSax: No memory for hscx.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
X 			return (1);
X 		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+			return (2);
+		}
X 		skb_queue_head_init(&bcs->rqueue);
X 		skb_queue_head_init(&bcs->squeue);
X 	}
- bcs->hw.hscx.tx_skb = NULL;
+	bcs->tx_skb = NULL;
X 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 	bcs->event = 0;
X 	bcs->hw.hscx.rcvidx = 0;
@@ -204,77 +252,74 @@
X 	return (0);
X }
X 
-static void
-hscx_manl1(struct PStack *st, int pr,
-	   void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- modehscx(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
X int
X setstack_hscx(struct PStack *st, struct BCState *bcs)
X {
-	if (open_hscxstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+ if (open_hscxstate(st->l1.hardware, bcs))
X 		return (-1);
X 	st->l1.bcs = bcs;
X 	st->l2.l2l1 = hscx_l2l1;
-	st->ma.manl1 = hscx_manl1;
X 	setstack_manager(st);
X 	bcs->st = st;
+	setstack_l1_B(st);
X 	return (0);
X }
X 
X HISAX_INITFUNC(void
X clear_pending_hscx_ints(struct IsdnCardState *cs))
X {
-	int val;
-	char tmp[64];
+	int val, eval;
X 
X 	val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
-	sprintf(tmp, "HSCX B ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX B ISTA %x", val);
X 	if (val & 0x01) {
-		val = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
-		sprintf(tmp, "HSCX B EXIR %x", val);
-		debugl1(cs, tmp);
-	} else if (val & 0x02) {
-		val = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
-		sprintf(tmp, "HSCX A EXIR %x", val);
-		debugl1(cs, tmp);
+		eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
+		debugl1(cs, "HSCX B EXIR %x", eval);
+	}
+	if (val & 0x02) {
+		eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
+		debugl1(cs, "HSCX A EXIR %x", eval);
X 	}
X 	val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
-	sprintf(tmp, "HSCX A ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX A ISTA %x", val);
X 	val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
-	sprintf(tmp, "HSCX B STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX B STAR %x", val);
X 	val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
-	sprintf(tmp, "HSCX A STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX A STAR %x", val);
+	/* disable all IRQ */
X 	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
X 	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
-	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
-	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
X }
X 
-HISAX_INITFUNC(void 
+HISAX_INITFUNC(void
X inithscx(struct IsdnCardState *cs))
X {
X 	cs->bcs[0].BC_SetStack = setstack_hscx;
X 	cs->bcs[1].BC_SetStack = setstack_hscx;
X 	cs->bcs[0].BC_Close = close_hscxstate;
X 	cs->bcs[1].BC_Close = close_hscxstate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
X 	modehscx(cs->bcs, 0, 0);
X 	modehscx(cs->bcs + 1, 0, 0);
+}
+
+HISAX_INITFUNC(void
+inithscxisac(struct IsdnCardState *cs, int part))
+{
+	if (part & 1) {
+		clear_pending_isac_ints(cs);
+		clear_pending_hscx_ints(cs);
+		initisac(cs);
+		inithscx(cs);
+	}
+	if (part & 2) {
+		/* Reenable all IRQ */
+		cs->writeisac(cs, ISAC_MASK, 0);
+		cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
+		cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
+		/* RESET Receiver and Transmitter */
+		cs->writeisac(cs, ISAC_CMDR, 0x41);
+	}
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/hscx.h linux/drivers/isdn/hisax/hscx.h
--- v2.3.3/linux/drivers/isdn/hisax/hscx.h	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/hscx.h	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: hscx.h,v 1.3 1997/07/27 21:38:35 keil Exp $
+/* $Id: hscx.h,v 1.4 1998/04/15 16:45:34 keil Exp $
X 
X  * hscx.h   HSCX specific defines
X  *
@@ -6,6 +6,9 @@
X  *
X  *
X  * $Log: hscx.h,v $
+ * Revision 1.4  1998/04/15 16:45:34  keil
+ * new init code
+ *
X  * Revision 1.3  1997/07/27 21:38:35  keil
X  * new B-channel interface
X  *
@@ -44,3 +47,4 @@
X extern void modehscx(struct BCState *bcs, int mode, int bc);
X extern void clear_pending_hscx_ints(struct IsdnCardState *cs);
X extern void inithscx(struct IsdnCardState *cs);
+extern void inithscxisac(struct IsdnCardState *cs, int part);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/hscx_irq.c linux/drivers/isdn/hisax/hscx_irq.c
--- v2.3.3/linux/drivers/isdn/hisax/hscx_irq.c	Thu May 14 18:42:40 1998
+++ linux/drivers/isdn/hisax/hscx_irq.c	Sun May 23 10:03:41 1999
@@ -1,12 +1,24 @@
-/* $Id: hscx_irq.c,v 1.7 1998/02/12 23:07:37 keil Exp $
+/* $Id: hscx_irq.c,v 1.11 1998/11/15 23:54:49 keil Exp $
X 
X  * hscx_irq.c     low level b-channel stuff for Siemens HSCX
X  *
- * Author     Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author     Karsten Keil (ke...@isdn4linux.de)
X  *
X  * This is an include file for fast inline IRQ stuff
X  *
X  * $Log: hscx_irq.c,v $
+ * Revision 1.11  1998/11/15 23:54:49  keil
+ * changes from 2.0
+ *
+ * Revision 1.10 1998/08/13 23:36:35 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.9  1998/06/24 14:44:51  keil
+ * Fix recovery of TX IRQ loss
+ *
+ * Revision 1.8  1998/04/10 10:35:22  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
X  * Revision 1.7  1998/02/12 23:07:37  keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -85,7 +97,7 @@
X 	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
X 		if (cs->debug & L1_DEB_WARN)
X 			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
-		WriteHSCXCMDR(cs, bcs->channel, 0x80);
+		WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
X 		bcs->hw.hscx.rcvidx = 0;
X 		return;
X 	}
@@ -93,17 +105,16 @@
X 	bcs->hw.hscx.rcvidx += count;
X 	save_flags(flags);
X 	cli();
-	READHSCXFIFO(cs, bcs->channel, ptr, count);
-	WriteHSCXCMDR(cs, bcs->channel, 0x80);
+	READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
X 	restore_flags(flags);
X 	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char tmp[256];
-		char *t = tmp;
+		char *t = bcs->blog;
X 
X 		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', count);
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
X 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, bcs->blog);
X 	}
X }
X 
@@ -120,36 +131,35 @@
X 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
X 		debugl1(cs, "hscx_fill_fifo");
X 
-	if (!bcs->hw.hscx.tx_skb)
+	if (!bcs->tx_skb)
X 		return;
- if (bcs->hw.hscx.tx_skb->len <= 0)
+	if (bcs->tx_skb->len <= 0)
X 		return;
X 
X 	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->hw.hscx.tx_skb->len > fifo_size) {
+	if (bcs->tx_skb->len > fifo_size) {
X 		more = !0;
X 		count = fifo_size;
X 	} else
-		count = bcs->hw.hscx.tx_skb->len;
+		count = bcs->tx_skb->len;
X 
-	waitforXFW(cs, bcs->channel);
+	waitforXFW(cs, bcs->hw.hscx.hscx);
X 	save_flags(flags);
X 	cli();
-	ptr = bcs->hw.hscx.tx_skb->data;
-	skb_pull(bcs->hw.hscx.tx_skb, count);
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
X 	bcs->tx_cnt -= count;
X 	bcs->hw.hscx.count += count;
-	WRITEHSCXFIFO(cs, bcs->channel, ptr, count);
-	WriteHSCXCMDR(cs, bcs->channel, more ? 0x8 : 0xa);
+	WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
X 	restore_flags(flags);
X 	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char tmp[256];
-		char *t = tmp;
+		char *t = bcs->blog;
X 
X 		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', count);
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
X 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, bcs->blog);
X 	}
X }
X 
@@ -161,7 +171,6 @@
X 	struct sk_buff *skb;
X 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
X 	int count;
-	char tmp[32];
X 
X 	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
X 		return;
@@ -173,11 +182,9 @@
X 				if (cs->debug & L1_DEB_WARN)
X 					debugl1(cs, "HSCX invalid frame");
X 			if ((r & 0x40) && bcs->mode)
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "HSCX RDO mode=%d",
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX RDO mode=%d",
X 						bcs->mode);
-					debugl1(cs, tmp);
-				}
X 			if (!(r & 0x20))
X 				if (cs->debug & L1_DEB_WARN)
X 					debugl1(cs, "HSCX CRC error");
@@ -189,10 +196,8 @@
X 				count = fifo_size;
X 			hscx_empty_fifo(bcs, count);
X 			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
-				if (cs->debug & L1_DEB_HSCX_FIFO) {
-					sprintf(tmp, "HX Frame %d", count);
-					debugl1(cs, tmp);
-				}
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
X 				if (!(skb = dev_alloc_skb(count)))
X 					printk(KERN_WARNING "HSCX: receive out of memory\n");
X 				else {
@@ -219,20 +224,20 @@
X 		}
X 	}
X 	if (val & 0x10) {	/* XPR */
-		if (bcs->hw.hscx.tx_skb) {
-			if (bcs->hw.hscx.tx_skb->len) {
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
X 				hscx_fill_fifo(bcs);
X 				return;
X 			} else {
X 				if (bcs->st->lli.l1writewakeup &&
- (PACKET_NOACK != bcs->hw.hscx.tx_skb->pkt_type))
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
X 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				dev_kfree_skb(bcs->hw.hscx.tx_skb);
+				dev_kfree_skb(bcs->tx_skb);
X 				bcs->hw.hscx.count = 0; 
-				bcs->hw.hscx.tx_skb = NULL;
+				bcs->tx_skb = NULL;
X 			}
X 		}
-		if ((bcs->hw.hscx.tx_skb = skb_dequeue(&bcs->squeue))) {
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
X 			bcs->hw.hscx.count = 0;
X 			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
X 			hscx_fill_fifo(bcs);
@@ -249,73 +254,60 @@
X 
X 	u_char exval;
X 	struct BCState *bcs;
-	char tmp[32];
X 
X 	if (val & 0x01) {
X 		bcs = cs->bcs + 1;
X 		exval = READHSCX(cs, 1, HSCX_EXIR);
-		if (exval == 0x40) {
+		if (exval & 0x40) {
X 			if (bcs->mode == 1)
X 				hscx_fill_fifo(bcs);
X 			else {
X 				/* Here we lost an TX interrupt, so
X 				   * restart transmitting the whole frame.
X 				 */
-				if (bcs->hw.hscx.tx_skb) {
-					skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count);
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
X 					bcs->tx_cnt += bcs->hw.hscx.count;
X 					bcs->hw.hscx.count = 0;
X 				}
-				WriteHSCXCMDR(cs, bcs->channel, 0x01);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "HSCX B EXIR %x Lost TX", exval);
-					debugl1(cs, tmp);
-				}
+				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
X 			}
-		} else if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX B EXIR %x", exval);
-			debugl1(cs, tmp);
-		}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B EXIR %x", exval);
X 	}
X 	if (val & 0xf8) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX B interrupt %x", val);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B interrupt %x", val);
X 		hscx_interrupt(cs, val, 1);
X 	}
X 	if (val & 0x02) {
X 		bcs = cs->bcs;
X 		exval = READHSCX(cs, 0, HSCX_EXIR);
-		if (exval == 0x40) {
+		if (exval & 0x40) {
X 			if (bcs->mode == L1_MODE_TRANS)
X 				hscx_fill_fifo(bcs);
X 			else {
X 				/* Here we lost an TX interrupt, so
X 				   * restart transmitting the whole frame.
X 				 */
-				if (bcs->hw.hscx.tx_skb) {
-					skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count);
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
X 					bcs->tx_cnt += bcs->hw.hscx.count;
X 					bcs->hw.hscx.count = 0;
X 				}
-				WriteHSCXCMDR(cs, bcs->channel, 0x01);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "HSCX A EXIR %x Lost TX", exval);
-					debugl1(cs, tmp);
-				}
+				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
X 			}
-		} else if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX A EXIR %x", exval);
-			debugl1(cs, tmp);
-		}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A EXIR %x", exval);
X 	}
X 	if (val & 0x04) {
X 		exval = READHSCX(cs, 0, HSCX_ISTA);
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX A interrupt %x", exval);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A interrupt %x", exval);
X 		hscx_interrupt(cs, exval, 0);
X 	}
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/ipac.h linux/drivers/isdn/hisax/ipac.h
--- v2.3.3/linux/drivers/isdn/hisax/ipac.h	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/ipac.h	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: ipac.h,v 1.2 1997/10/29 18:51:21 keil Exp $
+/* $Id: ipac.h,v 1.3 1998/04/15 16:48:09 keil Exp $
X 
X  * ipac.h   IPAC specific defines
X  *
@@ -6,6 +6,9 @@
X  *
X  *
X  * $Log: ipac.h,v $
+ * Revision 1.3  1998/04/15 16:48:09  keil
+ * IPAC_ATX added
+ *
X  * Revision 1.2  1997/10/29 18:51:21  keil
X  * New files
X  *
@@ -26,6 +29,7 @@
X #define IPAC_ACFG	0xC3
X #define IPAC_AOE	0xC4
X #define IPAC_ARX	0xC5
+#define IPAC_ATX	0xC5
X #define IPAC_PITA1	0xC6
X #define IPAC_PITA2	0xC7
X #define IPAC_POTA1	0xC8
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c
--- v2.3.3/linux/drivers/isdn/hisax/isac.c	Thu May 14 18:43:27 1998
+++ linux/drivers/isdn/hisax/isac.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,33 @@
-/* $Id: isac.c,v 1.12 1998/02/12 23:07:40 keil Exp $
+/* $Id: isac.c,v 1.18 1998/11/15 23:54:51 keil Exp $
X 
X  * isac.c   ISAC specific routines
X  *
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
X  *
X  * $Log: isac.c,v $
+ * Revision 1.18  1998/11/15 23:54:51  keil
+ * changes from 2.0
+ *
+ * Revision 1.17 1998/08/13 23:36:37 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.16 1998/05/25 12:58:01 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.15 1998/04/15 16:45:32 keil
+ * new init code
+ *
+ * Revision 1.14  1998/04/10 10:35:26  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 1.13  1998/03/07 22:57:01  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
X * Revision 1.12 1998/02/12 23:07:40 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -63,30 +85,17 @@
X 	int val;
X 
X 	val = cs->readisac(cs, ISAC_RBCH);
-	printk(KERN_INFO "%s ISAC version : %s\n", s, ISACVer[(val >> 5) & 3]);
+	printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]);
X }
X 
X static void
X ph_command(struct IsdnCardState *cs, unsigned int command)
X {
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "ph_command %x", command);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "ph_command %x", command);
X 	cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3);
X }
X 
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
X 
X static void
X isac_new_ph(struct IsdnCardState *cs)
@@ -95,28 +104,28 @@
X 		case (ISAC_IND_RS):
X 		case (ISAC_IND_EI):
X 			ph_command(cs, ISAC_CMD_DUI);
-			manl1_msg(cs, PH_RESET_IND, NULL);
+			l1_msg(cs, HW_RESET | INDICATION, NULL);
X 			break;
X 		case (ISAC_IND_DID):
-			manl1_msg(cs, PH_DEACT_CNF, NULL);
+			l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
X 			break;
X 		case (ISAC_IND_DR):
-			manl1_msg(cs, PH_DEACT_IND, NULL);
+			l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
X 			break;
X case (ISAC_IND_PU):
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
X 			break;
X case (ISAC_IND_RSY):
-			manl1_msg(cs, PH_RSYNC_IND, NULL);
+			l1_msg(cs, HW_RSYNC | INDICATION, NULL);
X 			break;
X case (ISAC_IND_ARD):
-			manl1_msg(cs, PH_INFO2_IND, NULL);
+			l1_msg(cs, HW_INFO2 | INDICATION, NULL);
X 			break;
X case (ISAC_IND_AI8):
-			manl1_msg(cs, PH_I4_P8_IND, NULL);
+			l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
X 			break;
X 		case (ISAC_IND_AI10):
-			manl1_msg(cs, PH_I4_P10_IND, NULL);
+			l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
X 			break;
X 		default:
X 			break;
@@ -130,13 +139,12 @@
X 	
X 	if (!cs)
X 		return;
-
X 	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
X 		if (cs->debug)
X 			debugl1(cs, "D-Channel Busy cleared");
X 		stptr = cs->stlist;
X 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
X 			stptr = stptr->next;
X 		}
X 	}
@@ -147,13 +155,13 @@
X 	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
X 		DChannel_proc_xmt(cs);
X 	if (test_and_clear_bit(D_RX_MON0, &cs->event))
-		test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
+		test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
X 	if (test_and_clear_bit(D_RX_MON1, &cs->event))
-		test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
+		test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
X 	if (test_and_clear_bit(D_TX_MON0, &cs->event))
-		test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
+		test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
X 	if (test_and_clear_bit(D_TX_MON1, &cs->event))
-		test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
+		test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
X }
X 
X void
@@ -165,13 +173,10 @@
X 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
X 		debugl1(cs, "isac_empty_fifo");
X 
-	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN) {
-		if (cs->debug & L1_DEB_WARN) {
-			char tmp[40];
-			sprintf(tmp, "isac_empty_fifo overrun %d",
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "isac_empty_fifo overrun %d",
X 				cs->rcvidx + count);
-			debugl1(cs, tmp);
-		}
X 		cs->writeisac(cs, ISAC_CMDR, 0x80);
X 		cs->rcvidx = 0;
X 		return;
@@ -184,12 +189,11 @@
X 	cs->writeisac(cs, ISAC_CMDR, 0x80);
X 	restore_flags(flags);
X 	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
+		char *t = cs->dlog;
X 
X 		t += sprintf(t, "isac_empty_fifo cnt %d", count);
X 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, cs->dlog);
X 	}
X }
X 
@@ -231,12 +235,11 @@
X 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
X 	add_timer(&cs->dbusytimer);
X 	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
+		char *t = cs->dlog;
X 
X 		t += sprintf(t, "isac_fill_fifo cnt %d", count);
X 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, cs->dlog);
X 	}
X }
X 
@@ -255,12 +258,9 @@
X 	struct sk_buff *skb;
X 	unsigned int count;
X 	long flags;
-	char tmp[32];
X 
-	if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "ISAC interrupt %x", val);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "ISAC interrupt %x", val);
X 	if (val & 0x80) {	/* RME */
X 		exval = cs->readisac(cs, ISAC_RSTA);
X 		if ((exval & 0x70) != 0x20) {
@@ -323,12 +323,20 @@
X 	}
X       afterXPR:
X 	if (val & 0x04) {	/* CISQ */
-		cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf;
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "ph_state change %x", cs->ph_state);
-			debugl1(cs, tmp);
+		exval = cs->readisac(cs, ISAC_CIR0);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC CIR0 %02X", exval );
+		if (exval & 2) {
+			cs->ph_state = (exval >> 2) & 0xf;
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "ph_state change %x", cs->ph_state);
+			isac_sched_event(cs, D_L1STATECHANGE);
+		}
+		if (exval & 1) {
+			exval = cs->readisac(cs, ISAC_CIR1);
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "ISAC CIR1 %02X", exval );
X 		}
-		isac_sched_event(cs, D_L1STATECHANGE);
X 	}
X 	if (val & 0x02) {	/* SIN */
X 		/* never */
@@ -337,16 +345,12 @@
X 	}
X 	if (val & 0x01) {	/* EXI */
X 		exval = cs->readisac(cs, ISAC_EXIR);
-		if (cs->debug & L1_DEB_WARN) {
-			sprintf(tmp, "ISAC EXIR %02x", exval);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "ISAC EXIR %02x", exval);
X 		if (exval & 0x04) {
X 			v1 = cs->readisac(cs, ISAC_MOSR);
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "ISAC MOSR %02x", v1);
-				debugl1(cs, tmp);
-			}
+			if (cs->debug & L1_DEB_MONITOR)
+				debugl1(cs, "ISAC MOSR %02x", v1);
X #if ARCOFI_USE
X 			if (v1 & 0x08) {
X 				if (!cs->mon_rx) {
@@ -370,10 +374,8 @@
X 					goto afterMONR0;
X 				}
X 				cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]);
-					debugl1(cs, tmp);
-				}
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]);
X 				if (cs->mon_rxp == 1) {
X 					cs->mocr |= 0x04;
X 					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
@@ -402,66 +404,70 @@
X 					goto afterMONR1;
X 				}
X 				cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
-					debugl1(cs, tmp);
-				}
-				if (cs->mon_rxp == 1) {
-					cs->mocr |= 0x40;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				}
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
+				cs->mocr |= 0x40;
+				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
X 			}
X 		      afterMONR1:
X 			if (v1 & 0x04) {
X 				cs->mocr &= 0xf0;
+				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
X 				cs->mocr |= 0x0a;
X 				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				isac_sched_event(cs, D_RX_MON0);
+				test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
X 			}
X 			if (v1 & 0x40) {
X 				cs->mocr &= 0x0f;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
X 				cs->mocr |= 0xa0;
X 				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				isac_sched_event(cs, D_RX_MON1);
+				test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
X 			}
X 			if (v1 & 0x02) {
-				if (!cs->mon_tx) {
+				if ((!cs->mon_tx) || (cs->mon_txc && 
+					(cs->mon_txp >= cs->mon_txc) && 
+					!(v1 & 0x08))) {
X 					cs->mocr &= 0xf0;
+					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
X 					cs->mocr |= 0x0a;
X 					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+					if (cs->mon_txc &&
+						(cs->mon_txp >= cs->mon_txc))
+						test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
X 					goto AfterMOX0;
X 				}
-				if (cs->mon_txp >= cs->mon_txc) {
-					if (cs->mon_txc)
-						isac_sched_event(cs, D_TX_MON0);
+				if (cs->mon_txc && (cs->mon_txp >= cs->mon_txc)) {
+					test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
X 					goto AfterMOX0;
X 				}
X 				cs->writeisac(cs, ISAC_MOX0,
X 					cs->mon_tx[cs->mon_txp++]);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]);
-					debugl1(cs, tmp);
-				}
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]);
X 			}
X 		      AfterMOX0:
X 			if (v1 & 0x20) {
-				if (!cs->mon_tx) {
+				if ((!cs->mon_tx) || (cs->mon_txc && 
+					(cs->mon_txp >= cs->mon_txc) && 
+					!(v1 & 0x80))) {
X 					cs->mocr &= 0x0f;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
X 					cs->mocr |= 0xa0;
X 					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+					if (cs->mon_txc &&
+						(cs->mon_txp >= cs->mon_txc))
+						test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
X 					goto AfterMOX1;
X 				}
-				if (cs->mon_txp >= cs->mon_txc) {
-					if (cs->mon_txc)
-						isac_sched_event(cs, D_TX_MON1);
+				if (cs->mon_txc && (cs->mon_txp >= cs->mon_txc)) {
+					test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
X 					goto AfterMOX1;
X 				}
X 				cs->writeisac(cs, ISAC_MOX1,
X 					cs->mon_tx[cs->mon_txp++]);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]);
-					debugl1(cs, tmp);
-				}
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]);
X 			}
X 		      AfterMOX1:
X #endif
@@ -470,14 +476,18 @@
X }
X 
X static void
-ISAC_l2l1(struct PStack *st, int pr, void *arg)
+ISAC_l1hw(struct PStack *st, int pr, void *arg)
X {
X 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
X 	struct sk_buff *skb = arg;
-	char str[64];
+ int val;
X 
X 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA |REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
X 			if (cs->tx_skb) {
X 				skb_queue_tail(&cs->sq, skb);
X #ifdef L2FRAME_DEBUG		/* psa */
@@ -485,12 +495,6 @@
X 					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
X #endif
X 			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data + 4, skb->len - 4,
-						  str);
-				}
X 				cs->tx_skb = skb;
X 				cs->tx_cnt = 0;
X #ifdef L2FRAME_DEBUG		/* psa */
@@ -500,19 +504,17 @@
X 				isac_fill_fifo(cs);
X 			}
X 			break;
-		case (PH_PULL_IND):
+		case (PH_PULL |INDICATION):
X 			if (cs->tx_skb) {
X 				if (cs->debug & L1_DEB_WARN)
X 					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
X 				skb_queue_tail(&cs->sq, skb);
X 				break;
X 			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
+			if (cs->debug & DEB_DLOG_HEX)
X 				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
X 			cs->tx_skb = skb;
X 			cs->tx_cnt = 0;
X #ifdef L2FRAME_DEBUG		/* psa */
@@ -521,28 +523,18 @@
X #endif
X 			isac_fill_fifo(cs);
X 			break;
-		case (PH_PULL_REQ):
+		case (PH_PULL | REQUEST):
X #ifdef L2FRAME_DEBUG		/* psa */
X 			if (cs->debug & L1_DEB_LAPD)
X 				debugl1(cs, "-> PH_REQUEST_PULL");
X #endif
X 			if (!cs->tx_skb) {
X 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
X 			} else
X 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
X 			break;
-	}
-}
-
-void
-isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	u_char val;
-	char tmp[32];
-	
-	switch(msg) {
-		case PH_RESET_REQ:
+		case (HW_RESET | REQUEST):
X 			if ((cs->ph_state == ISAC_IND_EI) ||
X 				(cs->ph_state == ISAC_IND_DR) ||
X 				(cs->ph_state == ISAC_IND_RS))
@@ -550,17 +542,17 @@
X 			else
X 				ph_command(cs, ISAC_CMD_RS);
X 			break;
-		case PH_ENABLE_REQ:
+		case (HW_ENABLE | REQUEST):
X ph_command(cs, ISAC_CMD_TIM);
X 			break;
-		case PH_INFO3_REQ:
+		case (HW_INFO3 | REQUEST):
X 			ph_command(cs, ISAC_CMD_AR8);
X 			break;
-		case PH_TESTLOOP_REQ:
+		case (HW_TESTLOOP | REQUEST):
X 			val = 0;
-			if (1 & (int) arg)
+			if (1 & (long) arg)
X 				val |= 0x0c;
-			if (2 & (int) arg)
+			if (2 & (long) arg)
X 				val |= 0x3;
X 			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
X 				/* IOM 1 Mode */
@@ -580,11 +572,21 @@
X 					cs->writeisac(cs, ISAC_ADF1, 0x0);
X 			}
X 			break;
-		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "isac_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
+		case (HW_DEACTIVATE | RESPONSE):
+			discard_queue(&cs->rq);
+			discard_queue(&cs->sq);
+			if (cs->tx_skb) {
+				dev_kfree_skb(cs->tx_skb);
+				cs->tx_skb = NULL;
X 			}
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				isac_sched_event(cs, D_CLEARBUSY);
+			break;
+		default:
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isac_l1hw unknown %04x", pr);
X 			break;
X 	}
X }
@@ -592,22 +594,29 @@
X void
X setstack_isac(struct PStack *st, struct IsdnCardState *cs)
X {
-	st->l2.l2l1 = ISAC_l2l1;
+	st->l1.l1hw = ISAC_l1hw;
X }
X 
X static void
X dbusy_timer_handler(struct IsdnCardState *cs)
X {
X 	struct PStack *stptr;
+	int	val;
X 
X 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		if (cs->debug)
+		if (cs->debug) {
X 			debugl1(cs, "D-Channel Busy");
+			val = cs->readisac(cs, ISAC_RBCH);
+			if (val & ISAC_RBCH_XAC)
+				debugl1(cs, "ISAC XAC");
+			else
+				debugl1(cs, "ISAC No XAC");
+		}
X 		test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
X 		stptr = cs->stlist;
X 		
X 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
X 			stptr = stptr->next;
X 		}
X 	}
@@ -617,7 +626,6 @@
X initisac(struct IsdnCardState *cs))
X {
X 	cs->tqueue.routine = (void *) (void *) isac_bh;
-	cs->l1cmd = isac_l1cmd;
X 	cs->setstack_d = setstack_isac;
X 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
X 	cs->dbusytimer.data = (long) cs;
@@ -648,35 +656,24 @@
X HISAX_INITFUNC(void
X clear_pending_isac_ints(struct IsdnCardState *cs))
X {
-	int val;
-	char tmp[64];
+	int val, eval;
X 
X 	val = cs->readisac(cs, ISAC_STAR);
-	sprintf(tmp, "ISAC STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC STAR %x", val);
X 	val = cs->readisac(cs, ISAC_MODE);
-	sprintf(tmp, "ISAC MODE %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC MODE %x", val);
X 	val = cs->readisac(cs, ISAC_ADF2);
-	sprintf(tmp, "ISAC ADF2 %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC ADF2 %x", val);
X 	val = cs->readisac(cs, ISAC_ISTA);
-	sprintf(tmp, "ISAC ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC ISTA %x", val);
X 	if (val & 0x01) {
-		val = cs->readisac(cs, ISAC_EXIR);
-		sprintf(tmp, "ISAC EXIR %x", val);
-		debugl1(cs, tmp);
-	} else if (val & 0x04) {
-		val = cs->readisac(cs, ISAC_CIR0);
-		sprintf(tmp, "ISAC CIR0 %x", val);
-		debugl1(cs, tmp);
-		cs->ph_state = (val >> 2) & 0xf;
-	} else {
-		cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf;
+		eval = cs->readisac(cs, ISAC_EXIR);
+		debugl1(cs, "ISAC EXIR %x", eval);
X 	}
+	val = cs->readisac(cs, ISAC_CIR0);
+	debugl1(cs, "ISAC CIR0 %x", val);
+	cs->ph_state = (val >> 2) & 0xf;
X 	isac_sched_event(cs, D_L1STATECHANGE);
+	/* Disable all IRQ */
X 	cs->writeisac(cs, ISAC_MASK, 0xFF);
-	cs->writeisac(cs, ISAC_MASK, 0);
-	cs->writeisac(cs, ISAC_CMDR, 0x41);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isac.h linux/drivers/isdn/hisax/isac.h
--- v2.3.3/linux/drivers/isdn/hisax/isac.h	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/isac.h	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: isac.h,v 1.4 1997/10/29 19:09:34 keil Exp $
+/* $Id: isac.h,v 1.5 1998/05/25 12:58:03 keil Exp $
X 
X  * isac.h   ISAC specific defines
X  *
@@ -6,6 +6,10 @@
X  *
X  *
X  * $Log: isac.h,v $
+ * Revision 1.5  1998/05/25 12:58:03  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X  * Revision 1.4  1997/10/29 19:09:34  keil
X  * new L1
X  *
@@ -26,16 +30,18 @@
X #define ISAC_STAR 0x21
X #define ISAC_CMDR 0x21
X #define ISAC_EXIR 0x24
-#define ISAC_RBCH 0x2a
X #define ISAC_ADF2 0x39
X #define ISAC_SPCR 0x30
X #define ISAC_ADF1 0x38
X #define ISAC_CIR0 0x31
X #define ISAC_CIX0 0x31
+#define ISAC_CIR1 0x33
+#define ISAC_CIX1 0x33
X #define ISAC_STCR 0x37
X #define ISAC_MODE 0x22
X #define ISAC_RSTA 0x27
X #define ISAC_RBCL 0x25
+#define ISAC_RBCH 0x2A
X #define ISAC_TIMR 0x23
X #define ISAC_SQXR 0x3b
X #define ISAC_MOSR 0x3a
@@ -44,6 +50,8 @@
X #define ISAC_MOX0 0x32
X #define ISAC_MOR1 0x34
X #define ISAC_MOX1 0x34
+
+#define ISAC_RBCH_XAC 0x80
X 
X #define ISAC_CMD_TIM	0x0
X #define ISAC_CMD_RS	0x1
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c
--- v2.3.3/linux/drivers/isdn/hisax/isar.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/isar.c	Sun May 23 10:03:41 1999
@@ -0,0 +1,937 @@
+/* $Id: isar.c,v 1.2 1998/11/15 23:54:53 keil Exp $
+
+ * isar.c   ISAR (Siemens PSB 7110) specific routines
+ *
+ * Author       Karsten Keil (ke...@isdn4linux.de)
+ *
+ *
+ * $Log: isar.c,v $
+ * Revision 1.2  1998/11/15 23:54:53  keil
+ * changes from 2.0
+ *
+ * Revision 1.1  1998/08/13 23:33:47  keil
+ * First version, only init
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isar.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+#define DBG_LOADFIRM	0
+#define DUMP_MBOXFRAME	2
+
+#define MIN(a,b) ((a<b)?a:b)
+
+void isar_setup(struct IsdnCardState *cs);
+
+static inline int
+waitforHIA(struct IsdnCardState *cs, int timeout)
+{
+
+	while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) {
+		udelay(1);
+		timeout--;
+	}
+	if (!timeout)
+		printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n");
+	return(timeout);
+}
+
+
+int
+sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
+	u_char *msg)
+{
+	long flags;
+	int i;
+	
+	if (!waitforHIA(cs, 4000))
+		return(0);
+#if DUMP_MBOXFRAME
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len);
+#endif
+	save_flags(flags);
+	cli();
+	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg);
+	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len);
+	cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0);
+	if (msg && len) {
+		cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]);
+		for (i=1; i<len; i++)
+			cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]);
+#if DUMP_MBOXFRAME>1
+		if (cs->debug & L1_DEB_HSCX_FIFO) {
+			char tmp[256], *t;
+			
+			i = len;
+			while (i>0) {
+				t = tmp;
+				t += sprintf(t, "sendmbox cnt %d", len);
+				QuickHex(t, &msg[len-i], (i>64) ? 64:i);
+				debugl1(cs, tmp);
+				i -= 64;
+			}
+		}
+#endif
+	}
+	cs->BC_Write_Reg(cs, 1, ISAR_HIS, his);
+	restore_flags(flags);
+	waitforHIA(cs, 10000);
+	return(1);
+}
+
+/* Call only with IRQ disabled !!! */
+inline void
+rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 21'
echo 'File patch-2.3.4 is continued in part 22'
echo 22 > _shar_seq_.tmp
#!/bin/sh
# this is part 23 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 23; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
-			break;
-		case PH_INFO2_IND:
-			FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
+		default:
+			if (cs->debug)
+				debugl1(cs, "dch_l2l1 msg %04X unhandled", pr);
X 			break;
-		case PH_I4_P8_IND:
-		case PH_I4_P10_IND:
-			FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+	}
+}
+
+void
+l1_msg(struct IsdnCardState *cs, int pr, void *arg) {
+	struct PStack *st;
+
+	st = cs->stlist;
+	
+	while (st) {
+		switch(pr) {
+			case (HW_RESET | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
+				break;
+			case (HW_DEACTIVATE | CONFIRM):
+				FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
+				break;
+			case (HW_DEACTIVATE | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
+				break;
+			case (HW_POWERUP | CONFIRM):
+				FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
+				break;
+			case (HW_RSYNC | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
+				break;
+			case (HW_INFO2 | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
+				break;
+			case (HW_INFO4_P8 | INDICATION):
+			case (HW_INFO4_P10 | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+				break;
+			default:
+				if (cs->debug)
+					debugl1(cs, "l1msg %04X unhandled", pr);
+				break;
+		}
+		st = st->next;
+	}
+}
+
+void
+l1_msg_b(struct PStack *st, int pr, void *arg) {
+	switch(pr) {
+		case (PH_ACTIVATE | REQUEST):
+			FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, NULL);
X 			break;
-		default:
-			if (cs->debug) {
-				sprintf(tmp, "dch_manl1 msg %04X unhandled", pr);
-				debugl1(cs, tmp);
-			}
+		case (PH_DEACTIVATE | REQUEST):
+			FsmEvent(&st->l1.l1m, EV_PH_DEACTIVATE, NULL);
X 			break;
X 	}
X }
@@ -1369,7 +856,7 @@
X {
X 	st->l1.hardware = cs;
X 	st->protocol = cs->protocol;
-	st->l1.l1m.fsm = &l1fsm;
+	st->l1.l1m.fsm = &l1fsm_d;
X 	st->l1.l1m.state = ST_L1_F3;
X 	st->l1.l1m.debug = cs->debug;
X 	st->l1.l1m.userdata = st;
@@ -1379,7 +866,22 @@
X 	setstack_tei(st);
X 	setstack_manager(st);
X 	st->l1.stlistp = &(cs->stlist);
-	st->ma.manl1 = dch_manl1;
+	st->l2.l2l1  = dch_l2l1;
X 	st->l1.Flags = 0;
X 	cs->setstack_d(st, cs);
+}
+
+void
+setstack_l1_B(struct PStack *st)
+{
+	struct IsdnCardState *cs = st->l1.hardware;
+
+	st->l1.l1m.fsm = &l1fsm_b;
+	st->l1.l1m.state = ST_L1_NULL;
+	st->l1.l1m.debug = cs->debug;
+	st->l1.l1m.userdata = st;
+	st->l1.l1m.userint = 0;
+	st->l1.l1m.printdebug = l1m_debug;
+	st->l1.Flags = 0;
+	FsmInitTimer(&st->l1.l1m, &st->l1.timer);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isdnl1.h linux/drivers/isdn/hisax/isdnl1.h
--- v2.3.3/linux/drivers/isdn/hisax/isdnl1.h	Wed Apr  1 16:20:58 1998
+++ linux/drivers/isdn/hisax/isdnl1.h	Sun May 23 10:03:41 1999
@@ -1,6 +1,16 @@
-/* $Id: isdnl1.h,v 2.5 1998/02/02 13:36:58 keil Exp $
+/* $Id: isdnl1.h,v 2.8 1998/11/15 23:54:59 keil Exp $
X 
X  * $Log: isdnl1.h,v $
+ * Revision 2.8  1998/11/15 23:54:59  keil
+ * changes from 2.0
+ *
+ * Revision 2.7  1998/09/30 22:21:55  keil
+ * cosmetics
+ *
+ * Revision 2.6  1998/05/25 12:58:06  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X  * Revision 2.5  1998/02/02 13:36:58  keil
X  * more debug
X  *
@@ -22,21 +32,6 @@
X  *
X  */
X 
-
-#define L2FRAME_DEBUG
-
-/* DEBUG Level */
-
-#define	L1_DEB_WARN		0x01
-#define	L1_DEB_INTSTAT		0x02
-#define	L1_DEB_ISAC		0x04
-#define	L1_DEB_ISAC_FIFO	0x08
-#define	L1_DEB_HSCX		0x10
-#define	L1_DEB_HSCX_FIFO	0x20
-#define	L1_DEB_LAPD	        0x40
-#define	L1_DEB_IPAC	        0x80
-#define	L1_DEB_RECEIVE_FRAME    0x100
-
X #define D_RCVBUFREADY	0
X #define D_XMTBUFREADY	1
X #define D_L1STATECHANGE	2
@@ -49,11 +44,12 @@
X #define B_RCVBUFREADY 0
X #define B_XMTBUFREADY 1
X 
-extern void debugl1(struct IsdnCardState *sp, char *msg);
+extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
X extern void DChannel_proc_xmt(struct IsdnCardState *cs);
X extern void DChannel_proc_rcv(struct IsdnCardState *cs);
-
+extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
+extern void l1_msg_b(struct PStack *st, int pr, void *arg);
X 
X #ifdef L2FRAME_DEBUG
-extern void Logl2Frame(struct IsdnCardState *sp, struct sk_buff *skb, char *buf, int dir);
+extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
X #endif
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c
--- v2.3.3/linux/drivers/isdn/hisax/isdnl2.c	Thu May 14 18:43:55 1998
+++ linux/drivers/isdn/hisax/isdnl2.c	Sun May 23 10:03:41 1999
@@ -1,12 +1,42 @@
-/* $Id: isdnl2.c,v 2.7 1998/02/12 23:07:47 keil Exp $
+/* $Id: isdnl2.c,v 2.16 1998/11/15 23:55:01 keil Exp $
X 
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *              based on the teles driver from Jan den Ouden
X  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
X  * Thanks to    Jan den Ouden
X  *              Fritz Elfert
X  *
X  * $Log: isdnl2.c,v $
+ * Revision 2.16  1998/11/15 23:55:01  keil
+ * changes from 2.0
+ *
+ * Revision 2.15 1998/08/13 23:36:42 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.14  1998/06/19 15:19:18  keil
+ * fix LAPB tx_cnt for none I-frames
+ *
+ * Revision 2.13  1998/06/18 23:17:20  keil
+ * LAPB bugfix
+ *
+ * Revision 2.12  1998/05/25 14:10:12  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.11 1998/05/25 12:58:08 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.9 1998/04/10 10:35:30 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.8 1998/03/07 22:57:04 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
X * Revision 2.7 1998/02/12 23:07:47 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -25,7 +55,7 @@
X  * Old stuff is still in the separate branch.
X  *
X  * Revision 2.2  1997/07/31 11:49:05  keil
- * Eroor handling for no TEI assign
+ * Error handling for no TEI assign
X  *
X  * Revision 2.1  1997/07/27 21:34:38  keil
X  * cosmetics
@@ -41,9 +71,9 @@
X #include "hisax.h"
X #include "isdnl2.h"
X 
-const char *l2_revision = "$Revision: 2.7 $";
+const char *l2_revision = "$Revision: 2.16 $";
X 
-static void l2m_debug(struct FsmInst *fi, char *s);
+static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
X 
X static
X struct Fsm l2fsm =
@@ -91,7 +121,6 @@
X 	EV_L2_MDL_ASSIGN,
X 	EV_L2_MDL_REMOVE,
X 	EV_L2_MDL_ERROR,
-	EV_L2_MDL_NOTEIPROC,
X 	EV_L1_DEACTIVATE,
X 	EV_L2_T200,
X 	EV_L2_T203,
@@ -117,7 +146,6 @@
X 	"EV_L2_MDL_ASSIGN",
X 	"EV_L2_MDL_REMOVE",
X 	"EV_L2_MDL_ERROR",
-	"EV_L2_MDL_NOTEIPROC",
X 	"EV_L1_DEACTIVATE",
X 	"EV_L2_T200",
X 	"EV_L2_T203",
@@ -161,26 +189,6 @@
X 	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
X }
X 
-static void
-discard_i_queue(struct PStack *st)
-{
-	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&st->l2.i_queue))) {
-		dev_kfree_skb(skb);
-	}
-}
-
-static void
-discard_ui_queue(struct PStack *st)
-{
-	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&st->l2.ui_queue))) {
-		dev_kfree_skb(skb);
-	}
-}
-
X inline void
X clear_exception(struct Layer2 *l2)
X {
@@ -224,20 +232,17 @@
X 	}
X }
X 
-static void
-enqueue_ui(struct PStack *st,
-	   struct sk_buff *skb)
-{
-	st->l2.l2l1(st, PH_DATA_REQ, skb);
-}
-
-static void
+inline static void
X enqueue_super(struct PStack *st,
X 	      struct sk_buff *skb)
X {
-	st->l2.l2l1(st, PH_DATA_REQ, skb);
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l1.bcs->tx_cnt += skb->len;
+	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
X }
X 
+#define enqueue_ui(a, b) enqueue_super(a, b)
+
X inline int
X IsUI(u_char * data, int ext)
X {
@@ -272,6 +277,16 @@
X }
X 
X inline int
+IsSFrame(u_char * data, int ext)
+{
+	register u_char d = *data;
+	
+	if (!ext)
+		d &= 0xf;
+	return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
+}
+
+inline int
X IsSABMX(u_char * data, int ext)
X {
X 	u_char d = data[0] & ~0x10;
@@ -393,15 +408,15 @@
X 	switch (event) {
X 		case EV_L2_UA:
X 			if (get_PollFlagFree(st, skb))
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'C');
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
X 			else
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'D');
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
X 			break;
X 		case EV_L2_DM:
X 			if (get_PollFlagFree(st, skb))
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'B');
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
X 			else {
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'E');
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
X 				establishlink(fi);
X 				test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
X 			}
@@ -415,9 +430,16 @@
X 	struct PStack *st = fi->userdata;
X 	int state = fi->state;
X 
-	FsmChangeState(fi, ST_L2_3); 
-	if (state == ST_L2_1)
-		st->l2.l2tei(st, MDL_ASSIGN_IND, NULL);
+	
+	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+		FsmChangeState(fi, ST_L2_4);
+		establishlink(fi);
+		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
+	} else {
+		FsmChangeState(fi, ST_L2_3);
+		if (state == ST_L2_1)
+			st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+	}
X }
X 
X static void
@@ -444,7 +466,7 @@
X 	skb_queue_tail(&st->l2.ui_queue, skb);
X 	if (fi->state == ST_L2_1) {
X 		FsmChangeState(fi, ST_L2_2);
-		st->l2.l2tei(st, MDL_ASSIGN_IND, NULL);
+		st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
X 	}
X 	if (fi->state > ST_L2_3)
X 		l2_send_ui(st);
@@ -458,10 +480,10 @@
X 
X 	skb_pull(skb, l2headersize(&st->l2, 1));
X 	if (skb->len > st->l2.maxlen) { 
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
X 		FreeSkb(skb);
X 	} else
-		st->l2.l2l3(st, DL_UNIT_DATA, skb);
+		st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
X }
X 
X static void
@@ -470,7 +492,7 @@
X 	struct PStack *st = fi->userdata;
X 
X 	if (fi->state != ST_L2_4)
-		discard_i_queue(st);
+		discard_queue(&st->l2.i_queue);
X 	if (fi->state != ST_L2_5)
X 		establishlink(fi);
X 	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
@@ -482,13 +504,13 @@
X 	struct PStack *st = fi->userdata;
X 
X 	if (fi->state == ST_L2_4) {
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		st->l2.l2l3(st, DL_RELEASE  | CONFIRM, NULL);
X 		return;
X 	} else if (fi->state == ST_L2_5) {
X 		test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
X 		return;
X 	}
-	discard_i_queue(st);
+	discard_queue(&st->l2.i_queue);
X 	FsmChangeState(fi, ST_L2_6);
X 	st->l2.rc = 0;
X 	send_uframe(st, DISC | 0x10, CMD);
@@ -510,14 +532,14 @@
X 	if (test_bit(FLG_ORIG, &st->l2.flag))
X 		rsp = !rsp;
X 	if (rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
X 		FreeSkb(skb);
X 		if ((state == ST_L2_7) || (state == ST_L2_8))
X 			establishlink(fi);
X 		return;
X 	}	
X 	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 		FreeSkb(skb);
X 		if ((state == ST_L2_7) || (state == ST_L2_8))
X 			establishlink(fi);
@@ -532,9 +554,9 @@
X 	if (ST_L2_5 == state)
X 		return;
X 	if (ST_L2_4 != state) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'F');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
X 		if (st->l2.vs != st->l2.va) {
-			discard_i_queue(st);
+			discard_queue(&st->l2.i_queue);
X 			est = 1;
X 		} else
X 			est = 0;
@@ -547,14 +569,14 @@
X 	FsmChangeState(fi, ST_L2_7);
X 	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
X 		FsmDelTimer(&st->l2.t200, 2);
-	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
+	FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
X 
X 	if (est)
-		st->l2.l2man(st, DL_ESTABLISH, NULL);
+		st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
X 
X 	if (ST_L2_8 == state)
X 		if (skb_queue_len(&st->l2.i_queue) && cansend(st))
-			st->l2.l2l1(st, PH_PULL_REQ, NULL);
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X }
X 
X static void
@@ -571,14 +593,14 @@
X 		rsp = !rsp;
X 
X 	if (rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
X 		FreeSkb(skb);
X 		if ((state == ST_L2_7) || (state == ST_L2_8))
X 			establishlink(fi);
X 		return;
X 	}	
X 	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 		FreeSkb(skb);
X 		if ((state == ST_L2_7) || (state == ST_L2_8))
X 			establishlink(fi);
@@ -600,8 +622,11 @@
X 			FsmDelTimer(&st->l2.t200, 2);
X 	}
X 	send_uframe(st, cmd | PollFlag, RSP);
-	if (rel)
-		st->l2.l2man(st, DL_RELEASE, NULL);
+	if (rel) {
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	}
X }
X 
X 
@@ -610,7 +635,8 @@
X {
X 	struct PStack *st = fi->userdata;
X 	struct sk_buff *skb = arg;
-	u_char PollFlag, est = 1;
+	int pr=-1;
+	u_char PollFlag;
X 	int state,rsp;
X 
X 	state = fi->state;
@@ -619,14 +645,14 @@
X 		rsp = !rsp;
X 
X 	if (!rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
X 		FreeSkb(skb);
X 		if ((state == ST_L2_7) || (state == ST_L2_8))
X 			establishlink(fi);
X 		return;
X 	}	
X 	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 		FreeSkb(skb);
X 		if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
X 			establishlink(fi);
@@ -643,30 +669,31 @@
X 		FsmDelTimer(&st->l2.t200, 2);
X 	if (fi->state == ST_L2_5) {
X 		if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) {
-			discard_i_queue(st);
+			discard_queue(&st->l2.i_queue);
X 			st->l2.rc = 0;
X 			send_uframe(st, DISC | 0x10, CMD);
X 			FsmChangeState(fi, ST_L2_6);
X 			FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 4);
X 			test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
X 		} else {
-			if (!test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
-				if (st->l2.vs != st->l2.va)
-					discard_i_queue(st);
-				else
-					est = 0;
+			if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
+				pr = DL_ESTABLISH | CONFIRM;
+			} else if (st->l2.vs != st->l2.va) {
+				discard_queue(&st->l2.i_queue);
+				pr = DL_ESTABLISH | INDICATION;
X 			}
X 			st->l2.vs = 0;
X 			st->l2.va = 0;
X 			st->l2.vr = 0;
X 			st->l2.sow = 0;
X 			FsmChangeState(fi, ST_L2_7);
-			FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
-			if (est)
-				st->l2.l2man(st, DL_ESTABLISH, NULL);
+			if (pr > -1)
+				st->l2.l2l3(st, pr, NULL);
X 		}
X 	} else {		/* ST_L2_6 */
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
X 		FsmChangeState(fi, ST_L2_4);
X 	}
X }
@@ -685,14 +712,14 @@
X 		rsp = !rsp;
X 
X 	if (!rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
X 		FreeSkb(skb);
X 		if ((state == ST_L2_7) || (state == ST_L2_8))
X 			establishlink(fi);
X 		return;
X 	}	
X 	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 		FreeSkb(skb);
X 		if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
X 			establishlink(fi);
@@ -700,15 +727,41 @@
X 	}
X 	PollFlag = get_PollFlagFree(st, skb);
X 	if (!PollFlag) {
-		establishlink(fi);
-		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+		if (fi->state == ST_L2_4) {
+			establishlink(fi);
+			test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+			FsmChangeState(fi, ST_L2_5);
+		} else if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8)) {
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
+			establishlink(fi);
+		}
X 	} else {
-		if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-			FsmDelTimer(&st->l2.t200, 2);
-	 	if (fi->state == ST_L2_5 && !test_bit(FLG_L3_INIT, &st->l2.flag))
-			discard_i_queue(st);
-		st->l2.l2man(st, DL_RELEASE, NULL);
-		FsmChangeState(fi, ST_L2_4);
+		switch (fi->state) {
+			case ST_L2_8:
+				 establishlink(fi);
+			case ST_L2_7:
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
+				break;
+			case ST_L2_4:
+				break;
+			case ST_L2_5:
+				if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
+					FsmDelTimer(&st->l2.t200, 2);
+				discard_queue(&st->l2.i_queue);
+				if (test_bit(FLG_LAPB, &st->l2.flag))
+					st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+				st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+				FsmChangeState(fi, ST_L2_4);
+				break;
+			case ST_L2_6:
+				if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
+					FsmDelTimer(&st->l2.t200, 2);
+				if (test_bit(FLG_LAPB, &st->l2.flag))
+					st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+				st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+				FsmChangeState(fi, ST_L2_4);
+				break;
+		}
X 	}
X }
X 
@@ -763,7 +816,7 @@
X {
X 	struct PStack *st = fi->userdata;
X 
-	st->ma.layer(st, MDL_ERROR_IND, (void *) 'J');
+	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
X 	establishlink(fi);
X }
X 
@@ -785,11 +838,13 @@
X 			if (p1 < 0)
X 				p1 += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
X 			p1 = (p1 + l2->sow) % l2->window;
+			if (test_bit(FLG_LAPB, &l2->flag))
+				st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
X 			skb_queue_head(&l2->i_queue, l2->windowar[p1]);
X 			l2->windowar[p1] = NULL;
X 		}
X 		restore_flags(flags);
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X 	}
X }
X 
@@ -818,9 +873,11 @@
X 			PollFlag = (skb->data[1] & 0x1) == 0x1;
X 			nr = skb->data[1] >> 1;
X 		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+			if (skb->len >2) {
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+				establishlink(fi);
+			}
X 			FreeSkb(skb);
-			establishlink(fi);
X 			return;
X 		}
X 	} else {
@@ -828,7 +885,7 @@
X 			PollFlag = (skb->data[0] & 0x10);
X 			nr = (skb->data[0] >> 5) & 0x7;
X 		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 			FreeSkb(skb);
X 			establishlink(fi);
X 			return;
@@ -839,7 +896,7 @@
X 	if ((!rsp) && PollFlag)
X 		enquiry_response(st);
X 	if (rsp && PollFlag)
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'A');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
X 	if (legalnr(st, nr)) {
X 		if (typ == REJ) {
X 			setva(st, nr);
@@ -862,13 +919,13 @@
X 			test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
X 		}
X 		if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
-			st->l2.l2l1(st, PH_PULL_REQ, NULL);
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X 	} else
X 		nrerrorrecovery(fi);
X 
X 	if ((fi->userint & LC_FLUSH_WAIT) && rsp && !(skb_queue_len(&st->l2.i_queue))) {
X 		fi->userint &= ~LC_FLUSH_WAIT;
-		st->l2.l2man(st, DL_FLUSH, NULL);
+		st->l2.l2l3(st, DL_FLUSH | INDICATION, NULL);
X 	}
X }
X 
@@ -883,7 +940,7 @@
X 	if (!((fi->state == ST_L2_5) && test_bit(FLG_L3_INIT, &st->l2.flag)))
X 		skb_queue_tail(&st->l2.i_queue, skb);
X 	if (fi->state == ST_L2_7)
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X }
X 
X static void
@@ -891,17 +948,15 @@
X {
X 	struct PStack *st = fi->userdata;
X 	struct sk_buff *skb = arg;
-	struct IsdnCardState *sp = st->l1.hardware;
X 	struct Layer2 *l2 = &(st->l2);
-	int PollFlag, ns, nr, i, hs, rsp;
-	char str[64];
+	int PollFlag, ns, nr, i, rsp;
X 
X 	rsp = *skb->data & 0x2;
X 	if (test_bit(FLG_ORIG, &l2->flag))
X 		rsp = !rsp;
X 
X 	if (rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
X 		FreeSkb(skb);
X 		establishlink(fi);
X 		return;
@@ -909,12 +964,10 @@
X 	i = l2addrsize(l2);
X 	if (test_bit(FLG_MOD128, &l2->flag)) {
X 		if (skb->len <= (i + 1)) {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
X 			FreeSkb(skb);
-			establishlink(fi);
X 			return;
X 		} else if ((skb->len - i - 1) > l2->maxlen) { 
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
X 			FreeSkb(skb);
X 			establishlink(fi);
X 			return;
@@ -924,12 +977,12 @@
X 		nr = (skb->data[i + 1] >> 1) & 0x7f;
X 	} else {
X 		if (skb->len <= i) {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 			FreeSkb(skb);
X 			establishlink(fi);
X 			return;
X 		} else if ((skb->len - i) > l2->maxlen) { 
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
X 			FreeSkb(skb);
X 			establishlink(fi);
X 			return;
@@ -944,20 +997,12 @@
X 	} else if (l2->vr == ns) {
X 		l2->vr = (l2->vr + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
X 		test_and_clear_bit(FLG_REJEXC, &l2->flag);
-		if (test_bit(FLG_LAPD, &l2->flag))
-			if (sp->dlogflag) {
-				hs = l2headersize(l2, 0);
-				LogFrame(st->l1.hardware, skb->data, skb->len);
-				sprintf(str, "Q.931 frame network->user tei %d", st->l2.tei);
-				dlogframe(st->l1.hardware, skb->data + hs,
-					  skb->len - hs, str);
-			}
X 		if (PollFlag)
X 			enquiry_response(st);
X 		else
X 			test_and_set_bit(FLG_ACK_PEND, &l2->flag);
X 		skb_pull(skb, l2headersize(l2, 0));
-		st->l2.l2l3(st, DL_DATA, skb);
+		st->l2.l2l3(st, DL_DATA | INDICATION, skb);
X 	} else {
X 		/* n(s)!=v(r) */
X 		FreeSkb(skb);
@@ -990,7 +1035,7 @@
X 	}
X 
X 	if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7))
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X 	if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
X 		enquiry_cr(st, RR, RSP, 0);
X }
@@ -1000,7 +1045,7 @@
X {
X 	struct PStack *st = fi->userdata;
X 
-	st->l2.tei = (int) arg;
+	st->l2.tei = (long) arg;
X 
X 	if (fi->state == ST_L2_3) {
X 		establishlink(fi);
@@ -1012,12 +1057,6 @@
X }
X 
X static void
-l2_no_tei(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L2_4);
-}
-
-static void
X l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
X {
X 	struct PStack *st = fi->userdata;
@@ -1028,9 +1067,11 @@
X 	} else if (st->l2.rc == st->l2.N200) {
X 		FsmChangeState(fi, ST_L2_4);
X 		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
-		discard_i_queue(st);
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'G');
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		discard_queue(&st->l2.i_queue);
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
X 	} else {
X 		st->l2.rc++;
X 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
@@ -1049,8 +1090,10 @@
X 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
X 	} else if (st->l2.rc == st->l2.N200) {
X 		FsmChangeState(fi, ST_L2_4);
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'H');
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
X 	} else {
X 		st->l2.rc++;
X 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
@@ -1146,14 +1189,14 @@
X 		memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
X 		FreeSkb(oskb);
X 	}
-	st->l2.l2l1(st, PH_PULL_IND, skb);
+	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
X 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
X 	if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
X 		FsmDelTimer(&st->l2.t203, 13);
X 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
X 	}
X 	if (skb_queue_len(&l2->i_queue) && cansend(st))
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X }
X 
X static void
@@ -1179,7 +1222,7 @@
X 			PollFlag = (skb->data[1] & 0x1) == 0x1;
X 			nr = skb->data[1] >> 1;
X 		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 			FreeSkb(skb);
X 			establishlink(fi);
X 			return;
@@ -1189,7 +1232,7 @@
X 			PollFlag = (skb->data[0] & 0x10);
X 			nr = (skb->data[0] >> 5) & 0x7;
X 		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 			FreeSkb(skb);
X 			establishlink(fi);
X 			return;
@@ -1213,10 +1256,10 @@
X 			invoke_retransmission(st, nr);
X 			FsmChangeState(fi, ST_L2_7);
X 			if (skb_queue_len(&l2->i_queue) && cansend(st))
-				st->l2.l2l1(st, PH_PULL_REQ, NULL);
+				st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
X 			else if (fi->userint & LC_FLUSH_WAIT) {
X 				fi->userint &= ~LC_FLUSH_WAIT;
-				st->l2.l2man(st, DL_FLUSH, NULL);
+				st->l2.l2l3(st, DL_FLUSH | INDICATION, NULL);
X 			}
X 		}
X 	} else {
@@ -1233,30 +1276,25 @@
X {
X 	struct PStack *st = fi->userdata;
X 	struct sk_buff *skb = arg;
-	char tmp[64];
X 
X 	skb_pull(skb, l2addrsize(&st->l2) + 1);
X 	if (test_bit(FLG_MOD128, &st->l2.flag)) {
X 		if (skb->len < 5)
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		else {
-			sprintf(tmp, "FRMR information %2x %2x %2x %2x %2x",
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+		else
+			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
X 				skb->data[0], skb->data[1], skb->data[2],
X 				skb->data[3], skb->data[4]);
-			l2m_debug(&st->l2.l2m, tmp);
-		}
X 	} else {
X 		if (skb->len < 3)
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		else {
-			sprintf(tmp, "FRMR information %2x %2x %2x",
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+		else
+			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
X 				skb->data[0], skb->data[1], skb->data[2]);
-			l2m_debug(&st->l2.l2m, tmp);
-		}
X 	}
X 	if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) ||		/* I or S */
X 	    (IsUA(skb->data, 0) && (fi->state == ST_L2_7))) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'K');
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
X 		establishlink(fi);
X 		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
X 	}
@@ -1268,14 +1306,14 @@
X {
X 	struct PStack *st = fi->userdata;
X 
-	discard_i_queue(st);
-	discard_ui_queue(st);
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
X 	st->l2.tei = -1;
X 	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
X 		FsmDelTimer(&st->l2.t200, 18);
X 	FsmDelTimer(&st->l2.t203, 19);
X 	if (fi->state != ST_L2_4)
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
X 	FsmChangeState(fi, ST_L2_1);
X }
X 
@@ -1283,33 +1321,45 @@
X l2_persistant_da(struct FsmInst *fi, int event, void *arg)
X {
X 	struct PStack *st = fi->userdata;
+	int rel = DL_RELEASE | INDICATION;
+	
X 	
-	discard_i_queue(st);
-	discard_ui_queue(st);
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
X 	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
X 		FsmDelTimer(&st->l2.t200, 18);
X 	FsmDelTimer(&st->l2.t203, 19);
-	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
X 	clear_exception(&st->l2);
X 	switch (fi->state) {
+		case ST_L2_1:
+			if (!test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+				break;
X 		case ST_L2_3:
-			st->l2.l2man(st, DL_RELEASE, NULL);
+			st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
X 		case ST_L2_2:
X 			FsmChangeState(fi, ST_L2_1);
X 			break;
-		case ST_L2_5:
X 		case ST_L2_6:
+			rel = DL_RELEASE | CONFIRM;
+		case ST_L2_5:
+			if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
+				rel = DL_RELEASE | CONFIRM;
X 		case ST_L2_7:
X 		case ST_L2_8:
-			st->l2.l2man(st, DL_RELEASE, NULL);
+			st->l2.l2l3(st, rel, NULL);
X 			FsmChangeState(fi, ST_L2_4);
X 			break;
+		case ST_L2_4:
+			if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+				st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+			break;
X 	}
+	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
+	test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
X }
X 
X static struct FsmNode L2FnList[] HISAX_INITDATA =
X {
-	{ST_L2_1, EV_L2_MDL_NOTEIPROC, l2_no_tei},
X 	{ST_L2_1, EV_L2_DL_ESTABLISH, l2_dl_establish},
X 	{ST_L2_2, EV_L2_DL_ESTABLISH, l2_dl_establish},
X 	{ST_L2_4, EV_L2_DL_ESTABLISH, l2_establish},
@@ -1359,8 +1409,8 @@
X 	{ST_L2_4, EV_L2_DM, l2_got_dm},
X 	{ST_L2_5, EV_L2_DM, l2_got_dm},
X 	{ST_L2_6, EV_L2_DM, l2_got_dm},
-	{ST_L2_7, EV_L2_DM, l2_mdl_error},
-	{ST_L2_8, EV_L2_DM, l2_mdl_error},
+	{ST_L2_7, EV_L2_DM, l2_got_dm},
+	{ST_L2_8, EV_L2_DM, l2_got_dm},
X 	{ST_L2_1, EV_L2_UI, l2_got_ui},
X 	{ST_L2_2, EV_L2_UI, l2_got_ui},
X 	{ST_L2_3, EV_L2_UI, l2_got_ui},
@@ -1381,6 +1431,7 @@
X 	{ST_L2_8, EV_L2_T200, l2_st78_tout_200},
X 	{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
X 	{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
+	{ST_L2_1, EV_L1_DEACTIVATE, l2_persistant_da},
X 	{ST_L2_2, EV_L1_DEACTIVATE, l2_persistant_da},
X 	{ST_L2_3, EV_L1_DEACTIVATE, l2_persistant_da},
X 	{ST_L2_4, EV_L1_DEACTIVATE, l2_persistant_da},
@@ -1400,19 +1451,19 @@
X 	int ret = 1, len;
X 
X 	switch (pr) {
-		case (PH_DATA_IND):
+		case (PH_DATA | INDICATION):
X 			datap = skb->data;
X 			len = l2addrsize(&st->l2);
X 			if (skb->len > len)
X 				datap += len;
X 			else {
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
X 				FreeSkb(skb);
X 				return;
X 			}
X 			if (!(*datap & 1))	/* I-Frame */
X 				ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
-			else if ((*datap & 3) == 1)	/* S-Frame */
+			else if (IsSFrame(datap, test_bit(FLG_MOD128, &st->l2.flag)))
X 				ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
X 			else if (IsUI(datap, test_bit(FLG_MOD128, &st->l2.flag)))
X 				ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
@@ -1427,23 +1478,39 @@
X 			else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag)))
X 				ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
X 			else {
-				ret = 0;
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
-				FreeSkb(skb);
+				ret = 1;
+				if ((st->l2.l2m.state == ST_L2_7) ||
+					(st->l2.l2m.state == ST_L2_8))
+					establishlink(&st->l2.l2m);
+				st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
X 			}
X 			if (ret) {
X 				FreeSkb(skb);
X 			}
X 			break;
-		case (PH_PULL_CNF):
+		case (PH_PULL | CONFIRM):
X 			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
X 			break;
-		case (PH_PAUSE_IND):
+		case (PH_PAUSE | INDICATION):
X 			test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag);
X 			break;
-		case (PH_PAUSE_CNF):
+		case (PH_PAUSE | CONFIRM):
X 			test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag);
X 			break;
+		case (PH_ACTIVATE | CONFIRM):
+		case (PH_ACTIVATE | INDICATION):
+			test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
+			if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+				FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+			break;
+		case (PH_DEACTIVATE | INDICATION):
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
+			FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
+			break;
+		default:
+			l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr);
+			break;
X 	}
X }
X 
@@ -1451,45 +1518,46 @@
X isdnl2_l3l2(struct PStack *st, int pr, void *arg)
X {
X 	switch (pr) {
-		case (DL_DATA):
+		case (DL_DATA | REQUEST):
X 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
X 				dev_kfree_skb((struct sk_buff *) arg);
X 			}
X 			break;
-		case (DL_UNIT_DATA):
+		case (DL_UNIT_DATA | REQUEST):
X 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
X 				dev_kfree_skb((struct sk_buff *) arg);
X 			}
X 			break;
-	}
-}
-
-static void
-isdnl2_manl2(struct PStack *st, int pr, void *arg)
-{
-	switch (pr) {
-		case (DL_ESTABLISH):
-			FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+		case (DL_ESTABLISH | REQUEST):
+			if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
+				if (test_bit(FLG_LAPD, &st->l2.flag) ||
+					test_bit(FLG_ORIG, &st->l2.flag)) {
+					FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+				}
+			} else {
+				if (test_bit(FLG_LAPD, &st->l2.flag) ||
+					test_bit(FLG_ORIG, &st->l2.flag)) {
+					test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
+				}
+				st->l2.l2l1(st, PH_ACTIVATE, NULL);
+			}
X 			break;
-		case (DL_RELEASE):
+		case (DL_RELEASE | REQUEST):
+			if (test_bit(FLG_LAPB, &st->l2.flag)) {
+				st->l2.l2l1(st, PH_DEACTIVATE, NULL);
+			}
X 			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE, arg);
X 			break;
-		case (MDL_NOTEIPROC):
-			FsmEvent(&st->l2.l2m, EV_L2_MDL_NOTEIPROC, NULL);
-			break;
-		case (DL_FLUSH):
+		case (DL_FLUSH | REQUEST):
X 			(&st->l2.l2m)->userint |= LC_FLUSH_WAIT;
X 			break;
-		case (PH_DEACTIVATE_IND):
-			FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
-			break;
-		case (MDL_ASSIGN_REQ):
+		case (MDL_ASSIGN | REQUEST):
X 			FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
X 			break;
-		case (MDL_REMOVE_REQ):
+		case (MDL_REMOVE | REQUEST):
X 			FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg);
X 			break;
-		case (MDL_ERROR_REQ):
+		case (MDL_ERROR | RESPONSE):
X 			FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg);
X 			break;
X 	}
@@ -1500,20 +1568,20 @@
X {
X 	FsmDelTimer(&st->l2.t200, 15);
X 	FsmDelTimer(&st->l2.t203, 16);
-	discard_i_queue(st);
-	discard_ui_queue(st);
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
X 	ReleaseWin(&st->l2);
X }
X 
X static void
-l2m_debug(struct FsmInst *fi, char *s)
+l2m_debug(struct FsmInst *fi, char *fmt, ...)
X {
+	va_list args;
X 	struct PStack *st = fi->userdata;
-	char tm[32], str[256];
X 
-	jiftime(tm, jiffies);
-	sprintf(str, "%s %s %s\n", tm, st->l2.debug_id, s);
-	HiSax_putstatus(st->l1.hardware, str);
+	va_start(args, fmt);
+	VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args);
+	va_end(args);
X }
X 
X void
@@ -1521,7 +1589,6 @@
X {
X 	st->l1.l1l2 = isdnl2_l1l2;
X 	st->l3.l3l2 = isdnl2_l3l2;
-	st->ma.manl2 = isdnl2_manl2;
X 
X 	skb_queue_head_init(&st->l2.i_queue);
X 	skb_queue_head_init(&st->l2.ui_queue);
@@ -1529,6 +1596,9 @@
X 	st->l2.debug = 0;
X 
X 	st->l2.l2m.fsm = &l2fsm;
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l2.l2m.state = ST_L2_4;
+	else
X 	st->l2.l2m.state = ST_L2_1;
X 	st->l2.l2m.debug = 0;
X 	st->l2.l2m.userdata = st;
@@ -1540,9 +1610,27 @@
X 	FsmInitTimer(&st->l2.l2m, &st->l2.t203);
X }
X 
+static void
+transl2_l3l2(struct PStack *st, int pr, void *arg)
+{
+	switch (pr) {
+		case (DL_DATA | REQUEST):
+		case (DL_UNIT_DATA | REQUEST):
+			st->l2.l2l1(st, PH_DATA | REQUEST, arg);
+			break;
+		case (DL_ESTABLISH | REQUEST):
+			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
+			break;
+		case (DL_RELEASE | REQUEST):
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+			break;
+	}
+}
+
X void
X setstack_transl2(struct PStack *st)
X {
+	st->l3.l3l2 = transl2_l3l2;
X }
X 
X void
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c
--- v2.3.3/linux/drivers/isdn/hisax/isdnl3.c	Wed Apr  1 16:20:59 1998
+++ linux/drivers/isdn/hisax/isdnl3.c	Sun May 23 10:03:41 1999
@@ -1,12 +1,27 @@
-/* $Id: isdnl3.c,v 2.5 1998/02/12 23:07:52 keil Exp $
+/* $Id: isdnl3.c,v 2.8 1998/11/15 23:55:04 keil Exp $
X 
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *              based on the teles driver from Jan den Ouden
X  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
X  * Thanks to    Jan den Ouden
X  *              Fritz Elfert
X  *
X  * $Log: isdnl3.c,v $
+ * Revision 2.8  1998/11/15 23:55:04  keil
+ * changes from 2.0
+ *
+ * Revision 2.7 1998/05/25 14:10:15 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.6 1998/05/25 12:58:11 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X * Revision 2.5 1998/02/12 23:07:52 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -47,7 +62,60 @@
X #include "isdnl3.h"
X #include <linux/config.h>
X 
-const char *l3_revision = "$Revision: 2.5 $";
+const char *l3_revision = "$Revision: 2.8 $";
+
+static
+struct Fsm l3fsm =
+{NULL, 0, 0, NULL, NULL};
+
+enum {
+	ST_L3_LC_REL,
+	ST_L3_LC_ESTAB_WAIT,
+	ST_L3_LC_REL_WAIT,
+	ST_L3_LC_ESTAB,
+};
+
+#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
+
+static char *strL3State[] =
+{
+	"ST_L3_LC_REL",
+	"ST_L3_LC_ESTAB_WAIT",
+	"ST_L3_LC_REL_WAIT",
+	"ST_L3_LC_ESTAB",
+};
+
+enum {
+	EV_ESTABLISH_REQ,
+	EV_ESTABLISH_IND,
+	EV_ESTABLISH_CNF,
+	EV_RELEASE_REQ,
+	EV_RELEASE_CNF,
+	EV_RELEASE_IND,
+};
+
+#define L3_EVENT_COUNT (EV_RELEASE_IND+1)
+
+static char *strL3Event[] =
+{
+	"EV_ESTABLISH_REQ",
+	"EV_ESTABLISH_IND",
+	"EV_ESTABLISH_CNF",
+	"EV_RELEASE_REQ",
+	"EV_RELEASE_CNF",
+	"EV_RELEASE_IND",
+};
+
+static void
+l3m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+	va_list args;
+	struct PStack *st = fi->userdata;
+
+	va_start(args, fmt);
+	VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
+	va_end(args);
+}
X 
X u_char *
X findie(u_char * p, int size, u_char ie, int wanted_set)
@@ -115,25 +183,11 @@
X }
X 
X void
-l3_debug(struct PStack *st, char *s)
-{
-	char str[256], tm[32];
-
-	jiftime(tm, jiffies);
-	sprintf(str, "%s l3 %s\n", tm, s);
-	HiSax_putstatus(st->l1.hardware, str);
-}
-
-void
X newl3state(struct l3_process *pc, int state)
X {
-	char tmp[80];
-
-	if (pc->debug & L3_DEB_STATE) {
-		sprintf(tmp, "newstate cr %d %d --> %d", pc->callref,
+	if (pc->debug & L3_DEB_STATE)
+		l3_debug(pc->st, "newstate cr %d %d --> %d", pc->callref,
X 			pc->state, state);
-		l3_debug(pc->st, tmp);
-	}
X 	pc->state = state;
X }
X 
@@ -197,7 +251,7 @@
X {
X 	struct sk_buff *skb = arg;
X 
-	HiSax_putstatus(st->l1.hardware, "L3 no D protocol\n");
+	HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
X 	if (skb) {
X 		dev_kfree_skb(skb);
X 	}
@@ -277,16 +331,25 @@
X 		pp = np;
X 		np = np->next;
X 	}
-	printk(KERN_ERR "HiSax internal L3 error CR not in list\n");
+	printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
+	l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
X };
X 
X void
-setstack_isdnl3(struct PStack *st, struct Channel *chanp)
+setstack_l3dc(struct PStack *st, struct Channel *chanp)
X {
X 	char tmp[64];
X 
X 	st->l3.proc   = NULL;
X 	st->l3.global = NULL;
+	skb_queue_head_init(&st->l3.squeue);
+	st->l3.l3m.fsm = &l3fsm;
+	st->l3.l3m.state = ST_L3_LC_REL;
+	st->l3.l3m.debug = 1;
+	st->l3.l3m.userdata = st;
+	st->l3.l3m.userint = 0;
+	st->l3.l3m.printdebug = l3m_debug;
+	strcpy(st->l3.debug_id, "L3DC ");
X 
X #ifdef	CONFIG_HISAX_EURO
X 	if (st->protocol == ISDN_PTYPE_EURO) {
@@ -321,6 +384,11 @@
X }
X 
X void
+isdnl3_trans(struct PStack *st, int pr, void *arg) {
+	st->l3.l3l2(st, pr, arg);
+}
+
+void
X releasestack_isdnl3(struct PStack *st)
X {
X 	while (st->l3.proc)
@@ -330,4 +398,136 @@
X 		kfree(st->l3.global);
X 		st->l3.global = NULL;
X 	}
+	discard_queue(&st->l3.squeue);
+}
+
+void
+setstack_l3bc(struct PStack *st, struct Channel *chanp)
+{
+
+	st->l3.proc   = NULL;
+	st->l3.global = NULL;
+	skb_queue_head_init(&st->l3.squeue);
+	st->l3.l3m.fsm = &l3fsm;
+	st->l3.l3m.state = ST_L3_LC_REL;
+	st->l3.l3m.debug = 1;
+	st->l3.l3m.userdata = st;
+	st->l3.l3m.userint = 0;
+	st->l3.l3m.printdebug = l3m_debug;
+	strcpy(st->l3.debug_id, "L3BC ");
+	st->lli.l4l3 = isdnl3_trans;
+}
+
+static void
+lc_activate(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
+	st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
+}
+
+static void
+lc_connect(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	FsmChangeState(fi, ST_L3_LC_ESTAB);
+	while ((skb = skb_dequeue(&st->l3.squeue))) {
+		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
+	}
+	st->l3.l3l4(st, DL_ESTABLISH | INDICATION, NULL);
+}
+
+static void
+lc_release_req(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if (fi->state == ST_L3_LC_ESTAB_WAIT)
+		FsmChangeState(fi, ST_L3_LC_REL);
+	else
+		FsmChangeState(fi, ST_L3_LC_REL_WAIT);
+	st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
+}
+
+static void
+lc_release_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L3_LC_REL);
+	discard_queue(&st->l3.squeue);
+	st->l3.l3l4(st, DL_RELEASE | INDICATION, NULL);
+}
+
+/* *INDENT-OFF* */
+static struct FsmNode L3FnList[] HISAX_INITDATA =
+{
+	{ST_L3_LC_REL,		EV_ESTABLISH_REQ,	lc_activate},
+	{ST_L3_LC_REL,		EV_ESTABLISH_IND,	lc_connect},
+	{ST_L3_LC_REL,		EV_ESTABLISH_CNF,	lc_connect},
+	{ST_L3_LC_ESTAB_WAIT,	EV_ESTABLISH_CNF,	lc_connect},
+	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_REQ,		lc_release_req},
+	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_IND,		lc_release_ind},
+	{ST_L3_LC_ESTAB,	EV_RELEASE_IND,		lc_release_ind},
+	{ST_L3_LC_ESTAB,	EV_RELEASE_REQ,		lc_release_req},
+	{ST_L3_LC_REL_WAIT,	EV_RELEASE_CNF,		lc_release_ind},
+	{ST_L3_LC_REL_WAIT,	EV_ESTABLISH_REQ,	lc_activate},
+};
+/* *INDENT-ON* */
+
+#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
+
+void
+l3_msg(struct PStack *st, int pr, void *arg)
+{
+	
+	switch (pr) {
+		case (DL_DATA | REQUEST):
+			if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
+				st->l3.l3l2(st, pr, arg);
+			} else {
+				struct sk_buff *skb = arg;
+
+				skb_queue_head(&st->l3.squeue, skb);
+				FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 
+			}
+			break;
+		case (DL_ESTABLISH | REQUEST):
+			FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
+			break;
+		case (DL_ESTABLISH | CONFIRM):
+			FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
+			break;
+		case (DL_ESTABLISH | INDICATION):
+			FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
+			break;
+		case (DL_RELEASE | INDICATION):
+			FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
+			break;
+		case (DL_RELEASE | CONFIRM):
+			FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
+			break;
+		case (DL_RELEASE | REQUEST):
+			FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
+			break;
+	}
+}
+
+HISAX_INITFUNC(void
+Isdnl3New(void))
+{
+	l3fsm.state_count = L3_STATE_COUNT;
+	l3fsm.event_count = L3_EVENT_COUNT;
+	l3fsm.strEvent = strL3Event;
+	l3fsm.strState = strL3State;
+	FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
+}
+
+void
+Isdnl3Free(void)
+{
+	FsmFree(&l3fsm);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/isdnl3.h linux/drivers/isdn/hisax/isdnl3.h
--- v2.3.3/linux/drivers/isdn/hisax/isdnl3.h	Wed Apr  1 16:20:59 1998
+++ linux/drivers/isdn/hisax/isdnl3.h	Sun May 23 10:03:41 1999
@@ -1,6 +1,17 @@
-/* $Id: isdnl3.h,v 2.0 1997/07/27 21:15:42 keil Exp $
+/* $Id: isdnl3.h,v 2.3 1998/11/15 23:55:06 keil Exp $
X 
X  * $Log: isdnl3.h,v $
+ * Revision 2.3  1998/11/15 23:55:06  keil
+ * changes from 2.0
+ *
+ * Revision 2.2 1998/05/25 14:10:17 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.1 1998/05/25 12:58:13 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X  * Revision 2.0  1997/07/27 21:15:42  keil
X  * New Callref based layer3
X  *
@@ -31,11 +42,12 @@
X 
X struct stateentry {
X 	int state;
-	u_char primitive;
+	int primitive;
X 	void (*rout) (struct l3_process *, u_char, void *);
X };
X 
-extern void l3_debug(struct PStack *st, char *s);
+#define l3_debug(st, fmt, args...) HiSax_putstatus(st->l1.hardware, "l3 ", fmt, ## args)
+
X extern void newl3state(struct l3_process *pc, int state);
X extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
X extern void L3DelTimer(struct L3Timer *t);
@@ -45,3 +57,4 @@
X extern struct l3_process *new_l3_process(struct PStack *st, int cr);
X extern void release_l3_process(struct l3_process *p);
X extern struct l3_process *getl3proc(struct PStack *st, int cr);
+extern void l3_msg(struct PStack *st, int pr, void *arg);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/ix1_micro.c linux/drivers/isdn/hisax/ix1_micro.c
--- v2.3.3/linux/drivers/isdn/hisax/ix1_micro.c	Wed Apr  1 16:21:01 1998
+++ linux/drivers/isdn/hisax/ix1_micro.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: ix1_micro.c,v 2.6 1998/02/11 17:28:09 keil Exp $
+/* $Id: ix1_micro.c,v 2.7 1998/04/15 16:44:31 keil Exp $
X 
X  * ix1_micro.c  low level stuff for ITK ix1-micro Rev.2 isdn cards
X  *              derived from the original file teles3.c from Karsten Keil
@@ -11,6 +11,9 @@
X  *              Beat Doebeli
X  *
X  * $Log: ix1_micro.c,v $
+ * Revision 2.7  1998/04/15 16:44:31  keil
+ * new init code
+ *
X * Revision 2.6 1998/02/11 17:28:09 keil
X  * Niccy PnP/PCI support
X  *
@@ -81,7 +84,7 @@
X #include "isdnl1.h"
X 
X extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.6 $";
+const char *ix1_revision = "$Revision: 2.7 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -277,10 +280,7 @@
X 			return(request_irq(cs->irq, &ix1micro_interrupt,
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/l3_1tr6.c linux/drivers/isdn/hisax/l3_1tr6.c
--- v2.3.3/linux/drivers/isdn/hisax/l3_1tr6.c	Wed Apr  1 16:21:02 1998
+++ linux/drivers/isdn/hisax/l3_1tr6.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,29 @@
-/* $Id: l3_1tr6.c,v 2.4 1998/02/12 23:07:57 keil Exp $
+/* $Id: l3_1tr6.c,v 2.8 1998/11/15 23:55:08 keil Exp $
X 
X  *  German 1TR6 D-channel protocol
X  *
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
X  *
X  *
X  * $Log: l3_1tr6.c,v $
+ * Revision 2.8  1998/11/15 23:55:08  keil
+ * changes from 2.0
+ *
+ * Revision 2.7 1998/08/13 23:36:45 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.6 1998/05/25 14:10:18 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.5 1998/05/25 12:58:14 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
X * Revision 2.4 1998/02/12 23:07:57 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -38,7 +56,7 @@
X #include <linux/ctype.h>
X 
X extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.4 $";
+const char *l3_1tr6_revision = "$Revision: 2.8 $";
X 
X #define MsgHead(ptr, cref, mty, dis) \
X 	*ptr++ = dis; \
@@ -56,66 +74,34 @@
X 		return;
X 	p = skb_put(skb, 4);
X 	MsgHead(p, pc->callref, mt, pd);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
X }
X 
-static int
-l31tr6_check_messagetype_validity(int mt, int pd) {
-/* verify if a message type exists */
-
-	if (pd == PROTO_DIS_N0)
-		switch(mt) {
-		   case MT_N0_REG_IND:
-		   case MT_N0_CANC_IND:
-		   case MT_N0_FAC_STA:
-		   case MT_N0_STA_ACK:
-		   case MT_N0_STA_REJ:
-		   case MT_N0_FAC_INF:
-		   case MT_N0_INF_ACK:
-		   case MT_N0_INF_REJ:
-		   case MT_N0_CLOSE:
-		   case MT_N0_CLO_ACK:
-			return(1);
-		   default:
-			return(0);
-		}
-	else if (pd == PROTO_DIS_N1)
-		switch(mt) {
-		   case MT_N1_ESC:
-		   case MT_N1_ALERT:
-		   case MT_N1_CALL_SENT:
-		   case MT_N1_CONN:
-		   case MT_N1_CONN_ACK:
-		   case MT_N1_SETUP:
-		   case MT_N1_SETUP_ACK:
-		   case MT_N1_RES:
-		   case MT_N1_RES_ACK:
-		   case MT_N1_RES_REJ:
-		   case MT_N1_SUSP:
-		   case MT_N1_SUSP_ACK:
-		   case MT_N1_SUSP_REJ:
-		   case MT_N1_USER_INFO:
-		   case MT_N1_DET:
-		   case MT_N1_DISC:
-		   case MT_N1_REL:
-		   case MT_N1_REL_ACK:
-		   case MT_N1_CANC_ACK:
-		   case MT_N1_CANC_REJ:
-		   case MT_N1_CON_CON:
-		   case MT_N1_FAC:
-		   case MT_N1_FAC_ACK:
-		   case MT_N1_FAC_CAN:
-		   case MT_N1_FAC_REG:
-		   case MT_N1_FAC_REJ:
-		   case MT_N1_INFO:
-		   case MT_N1_REG_ACK:
-		   case MT_N1_REG_REJ:
-		   case MT_N1_STAT:
-		   	return (1);
-		   default:
-		   	return(0);
-		}
-	return(0);
+static void
+l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
+{
+	StopAllL3Timer(pc);
+	newl3state(pc, 19);
+	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
+	L3AddTimer(&pc->timer, T308, CC_T308_1);
+}
+
+static void
+l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+
+	dev_kfree_skb(skb);
+	l3_1tr6_release_req(pc, 0, NULL);
+}
+
+static void
+l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
+{
+	dev_kfree_skb(skb);
+	if (pc->st->l3.debug & L3_DEB_WARN)
+		l3_debug(pc->st, msg);
+	l3_1tr6_release_req(pc, 0, NULL);
X }
X 
X static void
@@ -204,7 +190,7 @@
X 	L3DelTimer(&pc->timer);
X 	L3AddTimer(&pc->timer, T303, CC_T303);
X 	newl3state(pc, 1);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
X }
X 
X static void
@@ -220,17 +206,29 @@
X 	/* Channel Identification */
X 	p = skb->data;
X 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		bcfound++;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without bchannel");
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "setup wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
+			return;
+		}
+		if ((pc->para.bchannel = p[2] & 0x3))
+				bcfound++;
+	} else {
+		l3_1tr6_error(pc, "missing setup chanID", skb);
+		return;
+	}
X 
X 	p = skb->data;
X 	if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
X 		pc->para.setup.si1 = p[2];
X 		pc->para.setup.si2 = p[3];
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without service indicator");
+	} else {
+		l3_1tr6_error(pc, "missing setup SI", skb);
+		return;
+	}
X 
X 	p = skb->data;
X 	if ((p = findie(p, skb->len, WE0_destAddr, 0)))
@@ -261,7 +259,7 @@
X 			l3_debug(pc->st, tmp);
X 		}
X 		newl3state(pc, 6);
-		pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL);
+		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
X 	} else
X 		release_l3_process(pc);
X }
@@ -276,12 +274,22 @@
X 	p = skb->data;
X 	newl3state(pc, 2);
X 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
+			return;
+		}
X 		pc->para.bchannel = p[2] & 0x3;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
+	} else {
+		l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
+		return;
+	}
X 	dev_kfree_skb(skb);
X 	L3AddTimer(&pc->timer, T304, CC_T304);
-	pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
X }
X 
X static void
@@ -293,13 +301,27 @@
X 	L3DelTimer(&pc->timer);
X 	p = skb->data;
X 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "call sent wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
+			return;
+		}
+		if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
+			l3_1tr6_error(pc, "call sent wrong chanID value", skb);
+			return;
+		}
X 		pc->para.bchannel = p[2] & 0x3;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
+	} else {
+		l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
+		return;
+	}
X 	dev_kfree_skb(skb);
X 	L3AddTimer(&pc->timer, T310, CC_T310);
X 	newl3state(pc, 3);
-	pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
X }
X 
X static void
@@ -310,7 +332,7 @@
X 	dev_kfree_skb(skb);
X 	L3DelTimer(&pc->timer);	/* T304 */
X 	newl3state(pc, 4);
-	pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
X }
X 
X static void
@@ -330,7 +352,7 @@
X 		}
X 		if (tmpcharge > pc->para.chargeinfo) {
X 			pc->para.chargeinfo = tmpcharge;
-			pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
X 		}
X 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
X 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -356,10 +378,14 @@
X 	struct sk_buff *skb = arg;
X 
X 	L3DelTimer(&pc->timer);	/* T310 */
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connect date", skb);
+		return;
+	}
X 	newl3state(pc, 10);
X 	dev_kfree_skb(skb);
X 	pc->para.chargeinfo = 0;
-	pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
X }
X 
X static void
@@ -380,13 +406,16 @@
X 			pc->para.cause = 0;
X 			pc->para.loc = 0;
X 		}
-	} else
+	} else {
X 		pc->para.cause = -1;
+		l3_1tr6_error(pc, "missing REL cause", skb);
+		return;
+	}
X 	dev_kfree_skb(skb);
X 	StopAllL3Timer(pc);
X 	newl3state(pc, 0);
X 	l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
-	pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
X 	release_l3_process(pc);
X }
X 
@@ -399,7 +428,7 @@
X 	StopAllL3Timer(pc);
X 	newl3state(pc, 0);
X 	pc->para.cause = -1;
-	pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
X 	release_l3_process(pc);
X }
X 
@@ -421,7 +450,7 @@
X 		}
X 		if (tmpcharge > pc->para.chargeinfo) {
X 			pc->para.chargeinfo = tmpcharge;
-			pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
X 		}
X 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
X 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -448,9 +477,13 @@
X 			l3_debug(pc->st, "cause not found");
X 		pc->para.cause = -1;
X 	}
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connack date", skb);
+		return;
+	}
X 	dev_kfree_skb(skb);
X 	newl3state(pc, 12);
-	pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
X }
X 
X 
@@ -459,11 +492,15 @@
X {
X 	struct sk_buff *skb = arg;
X 
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connack date", skb);
+		return;
+	}
X 	dev_kfree_skb(skb);
X 	newl3state(pc, 10);
X 	pc->para.chargeinfo = 0;
X 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
X }
X 
X static void
@@ -502,7 +539,7 @@
X 	if (!(skb = l3_alloc_skb(l)))
X 		return;
X 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
X 	L3DelTimer(&pc->timer);
X 	L3AddTimer(&pc->timer, T313, CC_T313);
X }
@@ -545,20 +582,11 @@
X 	if (!(skb = l3_alloc_skb(l)))
X 		return;
X 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
X 	L3AddTimer(&pc->timer, T305, CC_T305);
X }
X 
X static void
-l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
-{
-	StopAllL3Timer(pc);
-	newl3state(pc, 19);
-	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
-	L3AddTimer(&pc->timer, T308, CC_T308_1);
-}
-
-static void
X l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
X {
X 	if (pc->N303 > 0) {
@@ -567,8 +595,8 @@
X 		l3_1tr6_setup_req(pc, pr, arg);
X 	} else {
X 		L3DelTimer(&pc->timer);
-		pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL);
-		release_l3_process(pc);
+		pc->para.cause = 0;
+		l3_1tr6_disconnect_req(pc, 0, NULL);
X 	}
X }
X 
@@ -578,7 +606,7 @@
X 	L3DelTimer(&pc->timer);
X 	pc->para.cause = 0xE6;
X 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
X }
X 
X static void
@@ -613,7 +641,7 @@
X 	if (!(skb = l3_alloc_skb(l)))
X 		return;
X 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
X 	L3AddTimer(&pc->timer, T308, CC_T308_1);
X }
X 
@@ -623,7 +651,7 @@
X 	L3DelTimer(&pc->timer);
X 	pc->para.cause = 0xE6;
X 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
X }
X 
X static void
@@ -632,7 +660,7 @@
X 	L3DelTimer(&pc->timer);
X 	pc->para.cause = 0xE6;
X 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
X }
X 
X static void
@@ -648,29 +676,29 @@
X l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
X {
X 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
X 	release_l3_process(pc);
X }
X /* *INDENT-OFF* */
X static struct stateentry downstl[] =
X {
X 	{SBIT(0),
-	 CC_SETUP_REQ, l3_1tr6_setup_req},
+	 CC_SETUP | REQUEST, l3_1tr6_setup_req},
X    	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
X     	 SBIT(10),
-    	 CC_DISCONNECT_REQ, l3_1tr6_disconnect_req},
+    	 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
X 	{SBIT(12),
-	 CC_RELEASE_REQ, l3_1tr6_release_req},
+	 CC_RELEASE | REQUEST, l3_1tr6_release_req},
X 	{ALL_STATES,
-	 CC_DLRL, l3_1tr6_reset},
+	 CC_DLRL | REQUEST, l3_1tr6_reset},
X 	{SBIT(6),
-	 CC_IGNORE, l3_1tr6_reset},
+	 CC_IGNORE | REQUEST, l3_1tr6_reset},
X 	{SBIT(6),
-	 CC_REJECT_REQ, l3_1tr6_disconnect_req},
+	 CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
X 	{SBIT(6),
-	 CC_ALERTING_REQ, l3_1tr6_alert_req},
+	 CC_ALERTING | REQUEST, l3_1tr6_alert_req},
X 	{SBIT(6) | SBIT(7),
-	 CC_SETUP_RSP, l3_1tr6_setup_rsp},
+	 CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
X 	{SBIT(1),
X 	 CC_T303, l3_1tr6_t303},
X 	{SBIT(2),
@@ -687,12 +715,14 @@
X 	 CC_T308_2, l3_1tr6_t308_2},
X };
X 
-static int downstl_len = sizeof(downstl) /
-sizeof(struct stateentry);
+#define DOWNSTL_LEN \
+	(sizeof(downstl) / sizeof(struct stateentry))
X 
X static struct stateentry datastln1[] =
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 23'
echo 'File patch-2.3.4 is continued in part 24'
echo 24 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 26 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 26; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+
+#define SEDL_IPAC_ANY_ADR 	0
+#define SEDL_IPAC_ANY_IPAC	2
+
+#define SEDL_IPAC_PCI_BASE	0
+#define SEDL_IPAC_PCI_ADR	0xc0
+#define SEDL_IPAC_PCI_IPAC	0xc8
X 
X #define SEDL_RESET      0x3	/* same as DOS driver */
X 
@@ -139,6 +206,29 @@
X }
X 
X static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+ return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
+}
+
+static u_char
X ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
X {
X 	return (readreg(cs->hw.sedl.adr,
@@ -152,6 +242,34 @@
X 		 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
X }
X 
+/* ISAR access routines
+ * mode = 0 access with IRQ on
+ * mode = 1 access with IRQ off
+ * mode = 2 access with IRQ off and using last offset
+ */
+  
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
+{	
+	if (mode == 0)
+		return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
+	else if (mode == 1)
+		byteout(cs->hw.sedl.adr, offset);
+	return(bytein(cs->hw.sedl.hscx));
+}
+
+static void
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
+{
+	if (mode == 0)
+		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
+	else {
+		if (mode == 1)
+			byteout(cs->hw.sedl.adr, offset);
+		byteout(cs->hw.sedl.hscx, value);
+	}
+}
+
X /*
X  * fast interrupt HSCX stuff goes here
X  */
@@ -180,7 +298,7 @@
X 		return;
X 	}
X 
-        if ((cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) && (*cs->busy_flag == 1)) {
+	if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
X           /* The card tends to generate interrupts while being removed
X              causing us to just crash the kernel. bad. */
X           printk(KERN_WARNING "Sedlbauer: card not available!\n");
@@ -223,11 +341,101 @@
X 	}
X }
X 
+static void
+sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 20;
+
+	if (!cs) {
+		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+ val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+ ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
+}
+
+static void
+sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	int cnt = 20;
+
+	if (!cs) {
+		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+		return;
+	}
+
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+      Start_ISAR:
+	if (val & ISAR_IRQSTA)
+		isar_int_main(cs);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+	if ((val & ISAR_IRQSTA) && --cnt) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "ISAR IntStat after IntRoutine");
+		goto Start_ISAR;
+	}
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+	if (val && --cnt) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (!cnt)
+		printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
+}
+
X void
X release_io_sedlbauer(struct IsdnCardState *cs)
X {
-	int bytecnt = 8;
+	int bytecnt = (cs->subtyp == SEDL_SPEED_FAX) ? 16 : 8;
X 
+	if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+		bytecnt = 256;
+	}
X 	if (cs->hw.sedl.cfg_reg)
X 		release_region(cs->hw.sedl.cfg_reg, bytecnt);
X }
@@ -237,16 +445,36 @@
X {
X 	long flags;
X 
-	if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA) {
-		byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
-		save_flags(flags);
-		sti();
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-		byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-		restore_flags(flags);
+	printk(KERN_INFO "Sedlbauer: resetting card\n");
+
+	if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
+	   (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
+		if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(1);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(1);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
+			restore_flags(flags);
+		} else {		
+			byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(1);
+			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(1);
+			restore_flags(flags);
+		}
X 	}
X }
X 
@@ -261,94 +489,256 @@
X 			release_io_sedlbauer(cs);
X 			return(0);
X 		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &sedlbauer_interrupt,
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				return(request_irq(cs->irq, &sedlbauer_interrupt_isar,
X 					I4L_IRQ_FLAG, "HiSax", cs));
+			} else if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+				return(request_irq(cs->irq, &sedlbauer_interrupt_ipac,
+					I4L_IRQ_FLAG, "HiSax", cs));
+			} else {
+ return(request_irq(cs->irq, &sedlbauer_interrupt,
+					I4L_IRQ_FLAG, "HiSax", cs));
+			}
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				clear_pending_isac_ints(cs);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				initisac(cs);
+				initisar(cs);
+				/* Reenable all IRQ */
+				cs->writeisac(cs, ISAC_MASK, 0);
+				/* RESET Receiver and Transmitter */
+				cs->writeisac(cs, ISAC_CMDR, 0x41);
+			} else {
+				inithscxisac(cs, 3);
+			}
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
+		case CARD_LOAD_FIRM:
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				if (isar_load_firmware(cs, arg))
+					return(1);
+				else 
+					ll_run(cs);
+			}
+			return(0);
X 	}
X 	return(0);
X }
X 
+
+#ifdef SEDLBAUER_PCI
+static  int pci_index __initdata = 0;
+#endif
+
X __initfunc(int
X setup_sedlbauer(struct IsdnCard *card))
X {
-	int bytecnt;
+	int bytecnt, ver, val;
X 	struct IsdnCardState *cs = card->cs;
X 	char tmp[64];
X 
X 	strcpy(tmp, Sedlbauer_revision);
X 	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+	
X  	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- 		cs->subtyp = SEDL_SPEED_CARD;
+ 		cs->subtyp = SEDL_SPEED_CARD_WIN;
+		cs->hw.sedl.bus = SEDL_BUS_ISA;
+		cs->hw.sedl.chip = SEDL_CHIP_TEST;
X  	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
X  		cs->subtyp = SEDL_SPEED_STAR;
+		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+		cs->hw.sedl.chip = SEDL_CHIP_TEST;
+ 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
+ 		cs->subtyp = SEDL_SPEED_FAX;
+		cs->hw.sedl.bus = SEDL_BUS_ISA;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
X  	} else
X 		return (0);
X 
X 	bytecnt = 8;
-	cs->hw.sedl.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (cs->subtyp == SEDL_SPEED_STAR) {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ISAC;
-		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_HSCX;
-		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
-		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
+	if (card->para[1]) {
+		cs->hw.sedl.cfg_reg = card->para[1];
+		cs->irq = card->para[0];
+		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+			bytecnt = 16;
+		}
X 	} else {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAC;
-		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX;
-		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_RESET_ON;
-		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_RESET_OFF;
-	}
-        
-	/* In case of the sedlbauer pcmcia card, this region is in use,
+/* Probe for Sedlbauer speed pci */
+#if SEDLBAUER_PCI
+#if CONFIG_PCI
+		for (; pci_index < 255; pci_index++) {
+			unsigned char pci_bus, pci_device_fn;
+			unsigned int ioaddr;
+			unsigned char irq;
+
+			if (pcibios_find_device (PCI_VENDOR_SEDLBAUER,
+						PCI_SPEEDPCI_ID, pci_index,
+						&pci_bus, &pci_device_fn) != 0) {
+				continue;
+			}
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+					PCI_INTERRUPT_LINE, &irq);
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_0, &ioaddr);
+			cs->irq = irq;
+			cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; 
+			if (!cs->hw.sedl.cfg_reg) {
+				printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			cs->hw.sedl.bus = SEDL_BUS_PCI;
+			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+			cs->subtyp = SEDL_SPEED_PCI;
+			bytecnt = 256;
+			byteout(cs->hw.sedl.cfg_reg, 0xff);
+			byteout(cs->hw.sedl.cfg_reg, 0x00);
+			byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+			byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+			break;
+		}	
+		if (pci_index == 255) {
+			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+			return(0);
+		}
+		pci_index++;
+#else
+		printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
+		return (0);
+#endif /* CONFIG_PCI */
+#endif /* SEDLBAUER_PCI */
+	}	
+	
+       	/* In case of the sedlbauer pcmcia card, this region is in use,
X            reserved for us by the card manager. So we do not check it
X            here, it would fail. */
-	if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA &&
-	   check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
+	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
+		check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
X 		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.sedl.cfg_reg,
-		       cs->hw.sedl.cfg_reg + bytecnt);
-		return (0);
+			"HiSax: %s config port %x-%x already in use\n",
+			CardType[card->typ],
+			cs->hw.sedl.cfg_reg,
+			cs->hw.sedl.cfg_reg + bytecnt);
+			return (0);
X 	} else {
X 		request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn");
X 	}
X 
X 	printk(KERN_INFO
-	       "Sedlbauer: defined at 0x%x IRQ %d\n",
+	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
X 	       cs->hw.sedl.cfg_reg,
+	       cs->hw.sedl.cfg_reg + bytecnt,
X 	       cs->irq);
-	printk(KERN_WARNING
-		       "Sedlbauer %s uses ports 0x%x-0x%x\n",
-		       Sedlbauer_Types[cs->subtyp],
-		       cs->hw.sedl.cfg_reg,
-		       cs->hw.sedl.cfg_reg + bytecnt);
X 
-	printk(KERN_INFO "Sedlbauer: resetting card\n");
-	reset_sedlbauer(cs);
-	cs->readisac = &ReadISAC;
-	cs->writeisac = &WriteISAC;
-	cs->readisacfifo = &ReadISACfifo;
-	cs->writeisacfifo = &WriteISACfifo;
X 	cs->BC_Read_Reg = &ReadHSCX;
X 	cs->BC_Write_Reg = &WriteHSCX;
X 	cs->BC_Send_Data = &hscx_fill_fifo;
X 	cs->cardmsg = &Sedl_card_msg;
-	ISACVersion(cs, "Sedlbauer:");
-	if (HscxVersion(cs, "Sedlbauer:")) {
-		printk(KERN_WARNING
-		    "Sedlbauer: wrong HSCX versions check IO address\n");
-		release_io_sedlbauer(cs);
-		return (0);
+
+/*
+ * testing ISA and PCMCIA Cards for IPAC, default is ISAC 
+ * do not test for PCI card, because ports are different
+ * and PCI card uses only IPAC (for the moment)
+ */	
+	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
+		val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
+        	        cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+	        if (val == 1) {
+		/* IPAC */
+                	cs->subtyp = SEDL_SPEED_WIN2_PC104;
+			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+				cs->subtyp = SEDL_SPEED_STAR2;
+			}
+			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		} else {
+		/* ISAC_HSCX oder ISAC_ISAR */
+			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
+				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+			}
+		}
+	}
+
+/*
+ * hw.sedl.chip is now properly set
+ */
+	printk(KERN_INFO "Sedlbauer: %s detected\n",
+		Sedlbauer_Types[cs->subtyp]);
+
+
+	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+	/* IPAC */
+		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+        	        cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+                	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+		} else {
+	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+        	        cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+                	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		}
+                test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+                cs->readisac = &ReadISAC_IPAC;
+                cs->writeisac = &WriteISAC_IPAC;
+                cs->readisacfifo = &ReadISACfifo_IPAC;
+                cs->writeisacfifo = &WriteISACfifo_IPAC;
+
+		val = readreg(cs->hw.sedl.adr,cs->hw.sedl.isac, IPAC_ID);
+                printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
+		reset_sedlbauer(cs);
+	} else {
+	/* ISAC_HSCX oder ISAC_ISAR */
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+			cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR;
+			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+			cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+			cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	
+			ISACVersion(cs, "Sedlbauer:");
+		
+			cs->BC_Read_Reg = &ReadISAR;
+			cs->BC_Write_Reg = &WriteISAR;
+			cs->BC_Send_Data = &isar_fill_fifo;
+			ver = ISARVersion(cs, "Sedlbauer:");
+			if (ver < 0) {
+				printk(KERN_WARNING
+					"Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
+				release_io_sedlbauer(cs);
+				return (0);
+			}
+		} else {
+			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+			} else {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+			}
+			ISACVersion(cs, "Sedlbauer:");
+		
+			if (HscxVersion(cs, "Sedlbauer:")) {
+				printk(KERN_WARNING
+					"Sedlbauer: wrong HSCX versions check IO address\n");
+				release_io_sedlbauer(cs);
+				return (0);
+			}
+			reset_sedlbauer(cs);
+		}
X 	}
X 	return (1);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/sportster.c linux/drivers/isdn/hisax/sportster.c
--- v2.3.3/linux/drivers/isdn/hisax/sportster.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/hisax/sportster.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.5 1998/02/02 13:29:46 keil Exp $
+/* $Id: sportster.c,v 1.7 1998/11/15 23:55:22 keil Exp $
X 
X  * sportster.c     low level stuff for USR Sportster internal TA
X  *
@@ -7,6 +7,12 @@
X  * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
X  *
X  * $Log: sportster.c,v $
+ * Revision 1.7  1998/11/15 23:55:22  keil
+ * changes from 2.0
+ *
+ * Revision 1.6 1998/04/15 16:44:35 keil
+ * new init code
+ *
X * Revision 1.5 1998/02/02 13:29:46 keil
X  * fast io
X  *
@@ -30,7 +36,7 @@
X #include "isdnl1.h"
X 
X extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.5 $";
+const char *sportster_revision = "$Revision: 1.7 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -187,12 +193,10 @@
X 			return(request_irq(cs->irq, &sportster_interrupt,
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 1);
X 			cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
X 			byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
+			inithscxisac(cs, 2);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/tei.c linux/drivers/isdn/hisax/tei.c
--- v2.3.3/linux/drivers/isdn/hisax/tei.c	Wed Apr  1 16:21:02 1998
+++ linux/drivers/isdn/hisax/tei.c	Sun May 23 10:03:41 1999
@@ -1,12 +1,34 @@
-/* $Id: tei.c,v 2.7 1998/02/12 23:08:11 keil Exp $
+/* $Id: tei.c,v 2.11 1998/11/15 23:55:24 keil Exp $
X 
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *              based on the teles driver from Jan den Ouden
X  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
X  * Thanks to    Jan den Ouden
X  *              Fritz Elfert
X  *
X  * $Log: tei.c,v $
+ * Revision 2.11  1998/11/15 23:55:24  keil
+ * changes from 2.0
+ *
+ * Revision 2.10  1998/05/25 14:08:10  keil
+ * HiSax 3.0
+ * fixed X.75 and leased line to work again
+ * Point2Point and fixed TEI are runtime options now:
+ *    hisaxctrl <id> 7 1  set PTP
+ *    hisaxctrl <id> 8 <TEIVALUE *2 >
+ *    set fixed TEI to TEIVALUE (0-63)
+ *
+ * Revision 2.9  1998/05/25 12:58:23  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8 1998/03/07 22:57:07 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
X * Revision 2.7 1998/02/12 23:08:11 keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -50,7 +72,7 @@
X #include "isdnl2.h"
X #include <linux/random.h>
X 
-const char *tei_revision = "$Revision: 2.7 $";
+const char *tei_revision = "$Revision: 2.11 $";
X 
X #define ID_REQUEST	1
X #define ID_ASSIGNED	2
@@ -151,26 +173,24 @@
X 	bp[2] = ri & 0xff;
X 	bp[3] = m_id;
X 	bp[4] = (tei << 1) | 1;
-	st->l2.l2l1(st, PH_DATA_REQ, skb);
+	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
X }
X 
X static void
X tei_id_request(struct FsmInst *fi, int event, void *arg)
X {
X 	struct PStack *st = fi->userdata;
-	char tmp[64];
X 
X 	if (st->l2.tei != -1) {
-		sprintf(tmp, "assign request for allready asigned tei %d",
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"assign request for allready asigned tei %d",
X 			st->l2.tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
X 		return;
X 	}
X 	st->ma.ri = random_ri();
-	if (st->ma.debug) {
-		sprintf(tmp, "assign request ri %d", st->ma.ri);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"assign request ri %d", st->ma.ri);
X 	put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
X 	FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
X 	FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
@@ -184,26 +204,24 @@
X 	struct sk_buff *skb = arg;
X 	struct IsdnCardState *cs;
X 	int ri, tei;
-	char tmp[64];
X 
X 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
X 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity assign ri %d tei %d", ri, tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity assign ri %d tei %d", ri, tei);
X 	if ((ost = findtei(st, tei))) {		/* same tei is in use */
X 		if (ri != ost->ma.ri) {
-			sprintf(tmp, "possible duplicate assignment tei %d", tei);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-			ost->l2.l2tei(ost, MDL_ERROR_REQ, NULL);
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"possible duplicate assignment tei %d", tei);
+			ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
X 		}
X 	} else if (ri == st->ma.ri) {
X 		FsmDelTimer(&st->ma.t202, 1);
X 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
-		st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) tei);
+		st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
X 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_ASSIGN_REQ, NULL);
+		cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
X 	}
X }
X 
@@ -213,14 +231,12 @@
X 	struct PStack *st = fi->userdata;
X 	struct sk_buff *skb = arg;
X int ri, tei;
-	char tmp[64];
X 
X 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
X 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity denied ri %d tei %d", ri, tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity denied ri %d tei %d", ri, tei);
X }
X 
X static void
@@ -229,13 +245,11 @@
X 	struct PStack *st = fi->userdata;
X 	struct sk_buff *skb = arg;
X int tei;
-	char tmp[64];
X 
X 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity check req tei %d", tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity check req tei %d", tei);
X 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
X 		FsmDelTimer(&st->ma.t202, 4);
X 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
@@ -250,19 +264,17 @@
X 	struct sk_buff *skb = arg;
X 	struct IsdnCardState *cs;
X 	int tei;
-	char tmp[64];
X 
X 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity remove tei %d", tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity remove tei %d", tei);
X 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
X 		FsmDelTimer(&st->ma.t202, 5);
X 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
-		st->ma.manl2(st, MDL_REMOVE_REQ, 0);
+		st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
X 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
X 	}
X }
X 
@@ -270,12 +282,10 @@
X tei_id_verify(struct FsmInst *fi, int event, void *arg)
X {
X 	struct PStack *st = fi->userdata;
-	char tmp[64];
X 
-	if (st->ma.debug) {
-		sprintf(tmp, "id verify request for tei %d", st->l2.tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"id verify request for tei %d", st->l2.tei);
X 	put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
X 	FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
X 	FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
@@ -286,24 +296,21 @@
X tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
X {
X 	struct PStack *st = fi->userdata;
- char tmp[64];
X 	struct IsdnCardState *cs;
X 
X 	if (--st->ma.N202) {
X 		st->ma.ri = random_ri();
-		if (st->ma.debug) {
-			sprintf(tmp, "assign req(%d) ri %d",
-				4 - st->ma.N202, st->ma.ri);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		}
+		if (st->ma.debug)
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"assign req(%d) ri %d", 4 - st->ma.N202,
+				st->ma.ri);
X 		put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
X 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
X 	} else {
-		sprintf(tmp, "assign req failed");
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		st->ma.manl2(st, MDL_ERROR_IND, 0);
+		st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
+		st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0);
X 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
X 		FsmChangeState(fi, ST_TEI_NOP);
X 	}
X }
@@ -312,23 +319,21 @@
X tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
X {
X 	struct PStack *st = fi->userdata;
- char tmp[64];
X 	struct IsdnCardState *cs;
X 
X 	if (--st->ma.N202) {
-		if (st->ma.debug) {
-			sprintf(tmp, "id verify req(%d) for tei %d",
+		if (st->ma.debug)
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"id verify req(%d) for tei %d",
X 				3 - st->ma.N202, st->l2.tei);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		}
X 		put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
X 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
X 	} else {
-		sprintf(tmp, "verify req for tei %d failed", st->l2.tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		st->ma.manl2(st, MDL_REMOVE_REQ, 0);
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"verify req for tei %d failed", st->l2.tei);
+		st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
X 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
X 		FsmChangeState(fi, ST_TEI_NOP);
X 	}
X }
@@ -338,31 +343,34 @@
X {
X 	struct sk_buff *skb = arg;
X int mt;
-	char tmp[64];
X 
- if (pr == PH_DATA_IND) {
+	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	if (pr == (PH_DATA | INDICATION)) {
X 		if (skb->len < 3) {
-			sprintf(tmp, "short mgr frame %d/3", skb->len);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"short mgr frame %ld/3", skb->len);
X 		} else if (((skb->data[0] >> 2) != TEI_SAPI) ||
X 			   ((skb->data[1] >> 1) != GROUP_TEI)) {
-			sprintf(tmp, "wrong mgr sapi/tei %x/%x",
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"wrong mgr sapi/tei %x/%x",
X 				skb->data[0], skb->data[1]);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
X 		} else if ((skb->data[2] & 0xef) != UI) {
-			sprintf(tmp, "mgr frame is not ui %x",
-				skb->data[2]);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"mgr frame is not ui %x", skb->data[2]);
X 		} else {
X 			skb_pull(skb, 3);
X 			if (skb->len < 5) {
-				sprintf(tmp, "short mgr frame %d/5", skb->len);
-				st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+				st->ma.tei_m.printdebug(&st->ma.tei_m,
+					"short mgr frame %ld/5", skb->len);
X 			} else if (skb->data[0] != TEI_ENTITY_ID) {
X 				/* wrong management entity identifier, ignore */
-				sprintf(tmp, "tei handler wrong entity id %x\n",
+				st->ma.tei_m.printdebug(&st->ma.tei_m,
+					"tei handler wrong entity id %x",
X 					skb->data[0]);
-				st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
X 			} else {
X 				mt = skb->data[3];
X 				if (mt == ID_ASSIGNED)
@@ -374,15 +382,14 @@
X 				else if (mt == ID_REMOVE)
X 					FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
X 				else {
-					sprintf(tmp, "tei handler wrong mt %x\n",
-						mt);
-					st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+					st->ma.tei_m.printdebug(&st->ma.tei_m,
+						"tei handler wrong mt %x\n", mt);
X 				}
X 			}
X 		}
X 	} else {
-		sprintf(tmp, "tei handler wrong pr %x\n", pr);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"tei handler wrong pr %x\n", pr);
X 	}
X 	dev_kfree_skb(skb);
X }
@@ -390,20 +397,24 @@
X static void
X tei_l2tei(struct PStack *st, int pr, void *arg)
X {
+	struct IsdnCardState *cs;
+
+	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+		if (pr == (MDL_ASSIGN | INDICATION)) {
+			if (st->ma.debug)
+				st->ma.tei_m.printdebug(&st->ma.tei_m,
+					"fixed assign tei %d", st->l2.tei);
+			st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
+			cs = (struct IsdnCardState *) st->l1.hardware;
+			cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
+		}
+		return;
+	}
X 	switch (pr) {
-		case (MDL_ASSIGN_IND):
-#ifdef TEI_FIXED
-			if (st->ma.debug) {
-				char tmp[64];
-				sprintf(tmp, "fixed assign tei %d", TEI_FIXED);
-				st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-			}
-			st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) TEI_FIXED);
-#else
+		case (MDL_ASSIGN | INDICATION):
X 			FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
-#endif
X 			break;
-		case (MDL_ERROR_REQ):
+		case (MDL_ERROR | REQUEST):
X 			FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
X 			break;
X 		default:
@@ -412,14 +423,14 @@
X }
X 
X static void
-tei_debug(struct FsmInst *fi, char *s)
+tei_debug(struct FsmInst *fi, char *fmt, ...)
X {
+	va_list args;
X 	struct PStack *st = fi->userdata;
-	char tm[32], str[256];
X 
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Tei %s\n", tm, s);
-	HiSax_putstatus(st->l1.hardware, str);
+	va_start(args, fmt);
+	VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
+	va_end(args);
X }
X 
X void
@@ -439,9 +450,8 @@
X }
X 
X void
-init_tei(struct IsdnCardState *sp, int protocol)
+init_tei(struct IsdnCardState *cs, int protocol)
X {
-
X }
X 
X void
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/teleint.c linux/drivers/isdn/hisax/teleint.c
--- v2.3.3/linux/drivers/isdn/hisax/teleint.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/hisax/teleint.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,17 @@
-/* $Id: teleint.c,v 1.5 1998/02/02 13:40:47 keil Exp $
+/* $Id: teleint.c,v 1.7 1998/11/15 23:55:26 keil Exp $
X 
X  * teleint.c     low level stuff for TeleInt isdn cards
X  *
- * Author     Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author     Karsten Keil (ke...@isdn4linux.de)
X  *
X  *
X  * $Log: teleint.c,v $
+ * Revision 1.7  1998/11/15 23:55:26  keil
+ * changes from 2.0
+ *
+ * Revision 1.6 1998/04/15 16:45:31 keil
+ * new init code
+ *
X * Revision 1.5 1998/02/02 13:40:47 keil
X  * fast io
X  *
@@ -32,7 +38,7 @@
X 
X extern const char *CardType[];
X 
-const char *TeleInt_revision = "$Revision: 1.5 $";
+const char *TeleInt_revision = "$Revision: 1.7 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -64,17 +70,20 @@
X readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
X {
X 	register u_char ret;
-	int max_delay = 2000;
+	register int max_delay = 20000;
+	register int i;
+	
X 	byteout(ale, off);
-
-	ret = HFC_BUSY & bytein(ale);
-	while (ret && --max_delay)
+	for (i = 0; i<size; i++) {
X 		ret = HFC_BUSY & bytein(ale);
-	if (!max_delay) {
-		printk(KERN_WARNING "TeleInt Busy not inaktive\n");
-		return;
+		while (ret && --max_delay)
+			ret = HFC_BUSY & bytein(ale);
+		if (!max_delay) {
+			printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+			return;
+		}
+		data[i] = bytein(adr);
X 	}
-	insb(adr, data, size);
X }
X 
X 
@@ -104,18 +113,21 @@
X writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
X {
X 	register u_char ret;
-	int max_delay = 2000;
-
+	register int max_delay = 20000;
+	register int i;
+	
X 	/* fifo write without cli because it's allready done  */
X 	byteout(ale, off);
-	ret = HFC_BUSY & bytein(ale);
-	while (ret && --max_delay)
+	for (i = 0; i<size; i++) {
X 		ret = HFC_BUSY & bytein(ale);
-	if (!max_delay) {
-		printk(KERN_WARNING "TeleInt Busy not inaktive\n");
-		return;
+		while (ret && --max_delay)
+			ret = HFC_BUSY & bytein(ale);
+		if (!max_delay) {
+			printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+			return;
+		}
+		byteout(adr, data[i]);
X 	}
-	outsb(adr, data, size);
X }
X 
X /* Interface functions */
@@ -157,11 +169,8 @@
X 		cs->hw.hfc.cip = reg;
X 		byteout(cs->hw.hfc.addr | 1, reg);
X 		ret = bytein(cs->hw.hfc.addr);
-		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
-			char tmp[32];
-			sprintf(tmp, "hfc RD %02x %02x", reg, ret);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+			debugl1(cs, "hfc RD %02x %02x", reg, ret);
X 	} else
X 		ret = bytein(cs->hw.hfc.addr | 1);
X 	return (ret);
@@ -174,11 +183,8 @@
X 	cs->hw.hfc.cip = reg;
X 	if (data)
X 		byteout(cs->hw.hfc.addr, value);
-	if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
-		char tmp[32];
-		sprintf(tmp, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+ debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
X }
X 
X static void
@@ -271,6 +277,9 @@
X 			inithfc(cs);
X 			clear_pending_isac_ints(cs);
X 			initisac(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
X 			cs->hw.hfc.timer.expires = jiffies + 1;
X 			add_timer(&cs->hw.hfc.timer);
X 			return(0);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/teles0.c linux/drivers/isdn/hisax/teles0.c
--- v2.3.3/linux/drivers/isdn/hisax/teles0.c	Wed Apr  1 16:21:02 1998
+++ linux/drivers/isdn/hisax/teles0.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: teles0.c,v 2.6 1998/02/03 23:27:47 keil Exp $
+/* $Id: teles0.c,v 2.8 1998/04/15 16:44:28 keil Exp $
X 
X  * teles0.c     low level stuff for Teles Memory IO isdn cards
X  *              based on the teles driver from Jan den Ouden
@@ -10,6 +10,12 @@
X  *              Beat Doebeli
X  *
X  * $Log: teles0.c,v $
+ * Revision 2.8  1998/04/15 16:44:28  keil
+ * new init code
+ *
+ * Revision 2.7 1998/03/07 22:57:08 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
X  * Revision 2.6  1998/02/03 23:27:47  keil
X  * IRQ 9
X  *
@@ -48,7 +54,7 @@
X 
X extern const char *CardType[];
X 
-const char *teles0_revision = "$Revision: 2.6 $";
+const char *teles0_revision = "$Revision: 2.8 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -62,7 +68,7 @@
X static inline void
X writeisac(unsigned int adr, u_char off, u_char data)
X {
-	writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off);
+	writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
X }
X 
X 
@@ -77,14 +83,14 @@
X writehscx(unsigned int adr, int hscx, u_char off, u_char data)
X {
X 	writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
-	       ((off & 1) ? 0x1ff : 0) + off);
+	       ((off & 1) ? 0x1ff : 0) + off); mb();
X }
X 
X static inline void
X read_fifo_isac(unsigned int adr, u_char * data, int size)
X {
X 	register int i;
-	register u_char *ad = (u_char *) (adr + 0x100);
+	register u_char *ad = (u_char *) ((long)adr + 0x100);
X 	for (i = 0; i < size; i++)
X 		data[i] = readb(ad);
X }
@@ -93,16 +99,17 @@
X write_fifo_isac(unsigned int adr, u_char * data, int size)
X {
X 	register int i;
-	register u_char *ad = (u_char *) (adr + 0x100);
-	for (i = 0; i < size; i++)
-		writeb(data[i], ad);
+	register u_char *ad = (u_char *) ((long)adr + 0x100);
+	for (i = 0; i < size; i++) {
+		writeb(data[i], ad); mb();
+	}
X }
X 
X static inline void
X read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
X {
X 	register int i;
-	register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
+	register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
X 	for (i = 0; i < size; i++)
X 		data[i] = readb(ad);
X }
@@ -111,9 +118,10 @@
X write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
X {
X 	int i;
-	register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
-	for (i = 0; i < size; i++)
-		writeb(data[i], ad);
+	register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
+	for (i = 0; i < size; i++) {
+		writeb(data[i], ad); mb();
+	}
X }
X 
X /* Interface functions */
@@ -264,9 +272,9 @@
X 		byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
X 		HZDELAY(HZ / 10 + 1);
X 	}
-	writeb(0, cs->hw.teles0.membase + 0x80);
+	writeb(0, cs->hw.teles0.membase + 0x80); mb();
X 	HZDELAY(HZ / 5 + 1);
-	writeb(1, cs->hw.teles0.membase + 0x80);
+	writeb(1, cs->hw.teles0.membase + 0x80); mb();
X 	HZDELAY(HZ / 5 + 1);
X 	restore_flags(flags);
X 	return(0);
@@ -286,10 +294,7 @@
X 			return(request_irq(cs->irq, &teles0_interrupt,
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c
--- v2.3.3/linux/drivers/isdn/hisax/teles3.c	Thu May 14 18:44:53 1998
+++ linux/drivers/isdn/hisax/teles3.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.7 1998/02/02 13:29:48 keil Exp $
+/* $Id: teles3.c,v 2.10 1999/02/15 14:37:15 cpetig Exp $
X 
X  * teles3.c     low level stuff for Teles 16.3 & PNP isdn cards
X  *
@@ -11,6 +11,15 @@
X  *              Beat Doebeli
X  *
X  * $Log: teles3.c,v $
+ * Revision 2.10  1999/02/15 14:37:15  cpetig
+ * oops, missed something in last commit
+ *
+ * Revision 2.9  1999/02/15 14:11:02  cpetig
+ * fixed a bug with Teles PCMCIA, it doesn't have a config register
+ *
+ * Revision 2.8  1998/04/15 16:44:30  keil
+ * new init code
+ *
X * Revision 2.7 1998/02/02 13:29:48 keil
X  * fast io
X  *
@@ -69,7 +78,7 @@
X #include "isdnl1.h"
X 
X extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.7 $";
+const char *teles3_revision = "$Revision: 2.10 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -214,15 +223,14 @@
X release_io_teles3(struct IsdnCardState *cs)
X {
X 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA)
-		release_region(cs->hw.teles3.cfg_reg, 97);
+		release_region(cs->hw.teles3.hscx[0], 97);
X 	else {
-		if (cs->hw.teles3.cfg_reg) {
+		if (cs->hw.teles3.cfg_reg)
X 			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
X 				release_region(cs->hw.teles3.cfg_reg, 1);
X 			} else {
X 				release_region(cs->hw.teles3.cfg_reg, 8);
X 			}
-		}
X 		release_ioregs(cs, 0x7);
X 	}
X }
@@ -305,10 +313,7 @@
X 			return(request_irq(cs->irq, &teles3_interrupt,
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
@@ -342,7 +347,7 @@
X 		cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
X 		cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
X 	} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		cs->hw.teles3.cfg_reg = card->para[1];
+		cs->hw.teles3.cfg_reg = 0;
X 		cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
X 		cs->hw.teles3.hscx[1] = card->para[1];
X 		cs->hw.teles3.isac = card->para[1] + 0x20;
@@ -362,12 +367,12 @@
X 	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
X 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
X 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (check_region((cs->hw.teles3.cfg_reg), 97)) {
+		if (check_region((cs->hw.teles3.hscx[0]), 97)) {
X 			printk(KERN_WARNING
X 			       "HiSax: %s ports %x-%x already in use\n",
X 			       CardType[cs->typ],
-			       cs->hw.teles3.cfg_reg,
-			       cs->hw.teles3.cfg_reg + 96);
+			       cs->hw.teles3.hscx[0],
+			       cs->hw.teles3.hscx[0] + 96);
X 			return (0);
X 		} else
X 			request_region(cs->hw.teles3.hscx[0], 97, "HiSax Teles PCMCIA");
@@ -400,13 +405,12 @@
X 			       CardType[cs->typ],
X 			       cs->hw.teles3.isac + 32,
X 			       cs->hw.teles3.isac + 64);
-			if (cs->hw.teles3.cfg_reg) {
+			if (cs->hw.teles3.cfg_reg)
X 				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
X 					release_region(cs->hw.teles3.cfg_reg, 1);
X 				} else {
X 					release_region(cs->hw.teles3.cfg_reg, 8);
X 				}
-			}
X 			return (0);
X 		} else
X 			request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac");
@@ -416,13 +420,12 @@
X 			       CardType[cs->typ],
X 			       cs->hw.teles3.hscx[0] + 32,
X 			       cs->hw.teles3.hscx[0] + 64);
-			if (cs->hw.teles3.cfg_reg) {
+			if (cs->hw.teles3.cfg_reg)
X 				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
X 					release_region(cs->hw.teles3.cfg_reg, 1);
X 				} else {
X 					release_region(cs->hw.teles3.cfg_reg, 8);
X 				}
-			}
X 			release_ioregs(cs, 1);
X 			return (0);
X 		} else
@@ -433,13 +436,12 @@
X 			       CardType[cs->typ],
X 			       cs->hw.teles3.hscx[1] + 32,
X 			       cs->hw.teles3.hscx[1] + 64);
-			if (cs->hw.teles3.cfg_reg) {
+			if (cs->hw.teles3.cfg_reg)
X 				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
X 					release_region(cs->hw.teles3.cfg_reg, 1);
X 				} else {
X 					release_region(cs->hw.teles3.cfg_reg, 8);
X 				}
-			}
X 			release_ioregs(cs, 3);
X 			return (0);
X 		} else
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/teles3c.c linux/drivers/isdn/hisax/teles3c.c
--- v2.3.3/linux/drivers/isdn/hisax/teles3c.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/hisax/teles3c.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,14 @@
-/* $Id: teles3c.c,v 1.2 1998/02/02 13:27:07 keil Exp $
+/* $Id: teles3c.c,v 1.3 1998/11/15 23:55:27 keil Exp $
X 
X  * teles3c.c     low level stuff for teles 16.3c
X  *
- * Author     Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author     Karsten Keil (ke...@isdn4linux.de)
X  *
X  *
X  * $Log: teles3c.c,v $
+ * Revision 1.3  1998/11/15 23:55:27  keil
+ * changes from 2.0
+ *
X * Revision 1.2 1998/02/02 13:27:07 keil
X  * New
X  *
@@ -20,14 +23,13 @@
X 
X extern const char *CardType[];
X 
-const char *teles163c_revision = "$Revision: 1.2 $";
+const char *teles163c_revision = "$Revision: 1.3 $";
X 
X static void
X t163c_interrupt(int intno, void *dev_id, struct pt_regs *regs)
X {
X 	struct IsdnCardState *cs = dev_id;
X 	u_char val, stat;
-	char tmp[32];
X 
X 	if (!cs) {
X 		printk(KERN_WARNING "teles3c: Spurious interrupt!\n");
@@ -36,16 +38,12 @@
X 	if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & 
X 		(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
X 		val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "teles3c: stat(%02x) s1(%02x)", stat, val);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "teles3c: stat(%02x) s1(%02x)", stat, val);
X 		hfc2bds0_interrupt(cs, val);
X 	} else {
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "teles3c: irq_no_irq stat(%02x)", stat);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "teles3c: irq_no_irq stat(%02x)", stat);
X 	}
X }
X 
@@ -110,13 +108,9 @@
X t163c_card_msg(struct IsdnCardState *cs, int mt, void *arg)
X {
X 	long flags;
-	char tmp[32];
X 
-	if (cs->debug & L1_DEB_ISAC) {
-		
-		sprintf(tmp, "teles3c: card_msg %x", mt);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "teles3c: card_msg %x", mt);
X 	switch (mt) {
X 		case CARD_RESET:
X 			reset_t163c(cs);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/telespci.c linux/drivers/isdn/hisax/telespci.c
--- v2.3.3/linux/drivers/isdn/hisax/telespci.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/telespci.c	Sun May 23 10:03:41 1999
@@ -0,0 +1,371 @@
+/* $Id: telespci.c,v 2.5 1998/11/15 23:55:28 keil Exp $
+
+ * telespci.c     low level stuff for Teles PCI isdn cards
+ *
+ * Author       Ton van Rosmalen 
+ *              Karsten Keil (ke...@temic-ech.spacenet.de)
+ *
+ *
+ * $Log: telespci.c,v $
+ * Revision 2.5  1998/11/15 23:55:28  keil
+ * changes from 2.0
+ *
+ * Revision 2.4  1998/10/05 09:38:08  keil
+ * Fix register addressing
+ *
+ * Revision 2.3  1998/05/25 12:58:26  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.1 1998/04/15 16:38:23 keil
+ * Add S0Box and Teles PCI support
+ *
+ *
+ */
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+#include <linux/pci.h>
+
+extern const char *CardType[];
+
+const char *telespci_revision = "$Revision: 2.5 $";
+
+#define ZORAN_PO_RQ_PEN	0x02000000
+#define ZORAN_PO_WR	0x00800000
+#define ZORAN_PO_GID0	0x00000000
+#define ZORAN_PO_GID1	0x00100000
+#define ZORAN_PO_GREG0	0x00000000
+#define ZORAN_PO_GREG1	0x00010000
+#define ZORAN_PO_DMASK	0xFF
+
+#define WRITE_ADDR_ISAC	(ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
+#define READ_DATA_ISAC	(ZORAN_PO_GID0 | ZORAN_PO_GREG1)
+#define WRITE_DATA_ISAC	(ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
+#define WRITE_ADDR_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
+#define READ_DATA_HSCX	(ZORAN_PO_GID1 | ZORAN_PO_GREG1)
+#define WRITE_DATA_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
+
+#define ZORAN_WAIT_NOBUSY	do { \
+					portdata = readl(adr + 0x200); \
+				} while (portdata & ZORAN_PO_RQ_PEN)
+
+static inline u_char
+readisac(unsigned int adr, u_char off)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	
+	/* set address for ISAC */
+	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	
+	/* read data from ISAC */
+	writel(READ_DATA_ISAC, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	return((u_char)(portdata & ZORAN_PO_DMASK));
+}
+
+static inline void
+writeisac(unsigned int adr, u_char off, u_char data)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	
+	/* set address for ISAC */
+	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+
+	/* write data to ISAC */
+	writel(WRITE_DATA_ISAC | data, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+}
+
+static inline u_char
+readhscx(unsigned int adr, int hscx, u_char off)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	/* set address for HSCX */
+	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	
+	/* read data from HSCX */
+	writel(READ_DATA_HSCX, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	return ((u_char)(portdata & ZORAN_PO_DMASK));
+}
+
+static inline void
+writehscx(unsigned int adr, int hscx, u_char off, u_char data)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	/* set address for HSCX */
+	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+
+	/* write data to HSCX */
+	writel(WRITE_DATA_HSCX | data, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+}
+
+static inline void
+read_fifo_isac(unsigned int adr, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* read data from ISAC */
+	for (i = 0; i < size; i++) {
+		/* set address for ISAC fifo */
+		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(READ_DATA_ISAC, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
+	}
+}
+
+static void
+write_fifo_isac(unsigned int adr, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* write data to ISAC */
+	for (i = 0; i < size; i++) {
+		/* set address for ISAC fifo */
+		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+	}
+}
+
+static inline void
+read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* read data from HSCX */
+	for (i = 0; i < size; i++) {
+		/* set address for HSCX fifo */
+		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(READ_DATA_HSCX, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
+	}
+}
+
+static inline void
+write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
+{
+	unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* write data to HSCX */
+	for (i = 0; i < size; i++) {
+		/* set address for HSCX fifo */
+		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		udelay(10);
+	}
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readisac(cs->hw.teles0.membase, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writeisac(cs->hw.teles0.membase, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	read_fifo_isac(cs->hw.teles0.membase, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	write_fifo_isac(cs->hw.teles0.membase, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readhscx(cs->hw.teles0.membase, hscx, offset));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writehscx(cs->hw.teles0.membase, hscx, offset, value);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 20
+	struct IsdnCardState *cs = dev_id;
+	u_char val, stat = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n");
+		return;
+	}
+	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
+	if (val) {
+		hscx_int_main(cs, val);
+		stat |= 1;
+	}
+	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
+	if (val) {
+		isac_interrupt(cs, val);
+		stat |= 2;
+	}
+	/* Clear interrupt register for Zoran PCI controller */
+	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
+
+	if (stat & 1) {
+		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
+	}
+	if (stat & 2) {
+		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	}
+}
+
+void
+release_io_telespci(struct IsdnCardState *cs)
+{
+	iounmap((void *)cs->hw.teles0.membase);
+}
+
+static int
+TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			return(0);
+		case CARD_RELEASE:
+			release_io_telespci(cs);
+			return(0);
+		case CARD_SETIRQ:
+			return(request_irq(cs->irq, &telespci_interrupt,
+					I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs));
+		case CARD_INIT:
+			inithscxisac(cs, 3);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+static 	struct pci_dev *dev_tel __initdata = NULL;
+
+__initfunc(int
+setup_telespci(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, telespci_revision);
+	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_TELESPCI)
+		return (0);
+
+#if CONFIG_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "TelesPCI: no PCI bus present\n");
+		return(0);
+	}
+	if ((dev_tel = pci_find_device (0x11DE, 0x6120, dev_tel))) {
+		cs->irq = dev_tel->irq;
+		if (!cs->irq) {
+			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
+			return(0);
+		}
+		cs->hw.teles0.membase = (u_int) ioremap(dev_tel->base_address[0],
+			PAGE_SIZE);
+		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
+			dev_tel->base_address[0], dev_tel->irq);
+	} else {
+		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
+		return(0);
+	}
+#else
+	printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
+	printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
+	return (0);
+#endif /* CONFIG_PCI */
+
+	/* Initialize Zoran PCI controller */
+	writel(0x00000000, cs->hw.teles0.membase + 0x28);
+	writel(0x01000000, cs->hw.teles0.membase + 0x28);
+	writel(0x01000000, cs->hw.teles0.membase + 0x28);
+	writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
+	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
+	writel(0x61000000, cs->hw.teles0.membase + 0x40);
+	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d mem:%x\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles0.membase);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &TelesPCI_card_msg;
+	ISACVersion(cs, "TelesPCI:");
+	if (HscxVersion(cs, "TelesPCI:")) {
+		printk(KERN_WARNING
+		 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
+		release_io_telespci(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.3.3/linux/drivers/isdn/icn/icn.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/icn/icn.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.49 1998/02/13 11:14:15 keil Exp $
+/* $Id: icn.c,v 1.56 1999/04/12 13:15:07 fritz Exp $
X 
X  * ISDN low-level module for the ICN active ISDN-Card.
X  *
@@ -19,6 +19,30 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: icn.c,v $
+ * Revision 1.56  1999/04/12 13:15:07  fritz
+ * Fixed a cast.
+ *
+ * Revision 1.55  1999/04/12 12:34:02  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.54  1999/01/05 18:29:39  he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.53  1998/06/17 19:51:28  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.52  1998/05/20 19:29:58  tsbogend
+ * fixed bug introduced by changes for new BSENT callback
+ *
+ * Revision 1.51  1998/03/07 22:29:55  fritz
+ * Adapted Detlef's chenges for 2.1.
+ *
+ * Revision 1.50  1998/03/07 17:41:54  detabc
+ * add d-channel connect and disconnect support statcallback
+ * from icn low-level to link->level
+ *
X  * Revision 1.49  1998/02/13 11:14:15  keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -209,7 +233,7 @@
X #undef MAP_DEBUG
X 
X static char
-*revision = "$Revision: 1.49 $";
+*revision = "$Revision: 1.56 $";
X 
X static int icn_addcard(int, char *, char *);
X 
@@ -232,10 +256,10 @@
X 	cli();
X 	card->xlen[channel] = 0;
X 	card->sndcount[channel] = 0;
-	if (card->xskb[channel]) {
+	if ((skb = card->xskb[channel])) {
X 		card->xskb[channel] = NULL;
X 		restore_flags(flags);
-		dev_kfree_skb(card->xskb[channel]);
+		dev_kfree_skb(skb);
X 	} else
X 		restore_flags(flags);
X }
@@ -529,6 +553,11 @@
X 					cmd.parm.length = card->xlen[channel];
X 					card->interface.statcallb(&cmd);
X 				}
+			} else {
+				save_flags(flags);
+				cli();
+				card->xskb[channel] = skb;
+				restore_flags(flags);
X 			}
X 			card->xmit_lock[channel] = 0;
X 			if (!icn_trymaplock_channel(card, mch))
@@ -580,8 +609,11 @@
X {
X 	{"BCON_",          ISDN_STAT_BCONN, 1},	/* B-Channel connected        */
X 	{"BDIS_",          ISDN_STAT_BHUP,  2},	/* B-Channel disconnected     */
-	{"DCON_",          ISDN_STAT_DCONN, 0},	/* D-Channel connected        */
-	{"DDIS_",          ISDN_STAT_DHUP,  0},	/* D-Channel disconnected     */
+	/*
+	** add d-channel connect and disconnect support to link-level
+	*/
+	{"DCON_",          ISDN_STAT_DCONN, 10},	/* D-Channel connected        */
+	{"DDIS_",          ISDN_STAT_DHUP,  11},	/* D-Channel disconnected     */
X 	{"DCAL_I",         ISDN_STAT_ICALL, 3},	/* Incoming call dialup-line  */
X 	{"DSCA_I",         ISDN_STAT_ICALL, 3},	/* Incoming call 1TR6-SPV     */
X 	{"FCALL",          ISDN_STAT_ICALL, 4},	/* Leased line connection up  */
@@ -630,7 +662,33 @@
X 	cmd.driver = card->myid;
X 	cmd.arg = channel;
X 	switch (action) {
+	case 11:
+			save_flags(flags);
+			cli();
+			icn_free_queue(card,channel);
+			card->rcvidx[channel] = 0;
+
+			if (card->flags & 
+			    ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) {
+				
+				isdn_ctrl ncmd;
+				
+				card->flags &= ~((channel)?
+						 ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE);
+				
+				memset(&ncmd, 0, sizeof(ncmd));
+				
+				ncmd.driver = card->myid;
+				ncmd.arg = channel;
+				ncmd.command = ISDN_STAT_BHUP;
+				restore_flags(flags);
+				card->interface.statcallb(&cmd);
+			} else
+				restore_flags(flags);
+			
+			break;
X 		case 1:
+			icn_free_queue(card,channel);
X 			card->flags |= (channel) ?
X 			    ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
X 			break;
@@ -1539,7 +1597,7 @@
X 						c->parm.num[0] ? "N" : "ALL", c->parm.num);
X 				} else
X 					sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
-						c->parm.num[0] ? c->parm.num : "0123456789");
+						c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
X 				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 26'
echo 'File patch-2.3.4 is continued in part 27'
echo 27 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 25 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 25; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
--- v2.3.3/linux/drivers/isdn/hisax/lmgr.c	Wed Apr  1 16:21:02 1998
+++ linux/drivers/isdn/hisax/lmgr.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,21 @@
-/* $Id: lmgr.c,v 1.2 1997/10/29 19:09:34 keil Exp $
+/* $Id: lmgr.c,v 1.5 1998/11/15 23:55:12 keil Exp $
X 
- * Author       Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author       Karsten Keil (ke...@isdn4linux.de)
X  *
X  *
X  *  Layermanagement module
X  *
X  * $Log: lmgr.c,v $
+ * Revision 1.5  1998/11/15 23:55:12  keil
+ * changes from 2.0
+ *
+ * Revision 1.4 1998/05/25 12:58:19 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.3 1998/03/07 22:57:06 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
X * Revision 1.2 1997/10/29 19:09:34 keil
X  * new L1
X  *
@@ -26,7 +36,7 @@
X 		case 'D':
X 		case 'G':
X 		case 'H':
-			st->l2.l2tei(st, MDL_ERROR_REQ, NULL);
+			st->l2.l2tei(st, MDL_ERROR | REQUEST, NULL);
X 			break;
X 	}
X }
@@ -34,17 +44,15 @@
X static void
X hisax_manager(struct PStack *st, int pr, void *arg)
X {
-	char tm[32], str[256];
-	int Code;
+	long Code;
X 
X 	switch (pr) {
-		case MDL_ERROR_IND:
-			Code = (int) arg;
-			jiftime(tm, jiffies);
-			sprintf(str, "%s manager: MDL_ERROR %c %s\n", tm,
-				Code, test_bit(FLG_LAPD, &st->l2.flag) ?
+		case (MDL_ERROR | INDICATION):
+			Code = (long) arg;
+			HiSax_putstatus(st->l1.hardware, "manager: MDL_ERROR",
+				"%c %s\n", (char)Code, 
+				test_bit(FLG_LAPD, &st->l2.flag) ?
X 				"D-channel" : "B-channel");
-			HiSax_putstatus(st->l1.hardware, str);
X 			if (test_bit(FLG_LAPD, &st->l2.flag))
X 				error_handling_dchan(st, Code);
X 			break;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc
--- v2.3.3/linux/drivers/isdn/hisax/md5sums.asc	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/md5sums.asc	Sun May 23 10:03:41 1999
@@ -0,0 +1,29 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+# This are valid md5sums for certificated HiSax driver.
+# The certification is valid only if the md5sums of all files match.
+# The certification is valid only for ELSA QuickStep cards in the moment.
+# Read ../../../Documentation/isdn/HiSax.cert for more informations.
+# 
+a273c532aec063574273ee519975cd9a  isac.c
+27c5c5bfa2ceabf02e2e6d686b03abde  isdnl1.c
+8c89ac659d3188ab997fb575da22b566  isdnl2.c
+d0fa912aa284b8fd19fed86b65999f6f  isdnl3.c
+1bce120740b615006286ad9b2d7fcdcb  tei.c
+8845f88dd17917d9b58badeff1605057  callc.c
+f3ec2a634f06074d16167aaba02b6dc1  cert.c
+71840ec8189f42b0db86fb38e5e5984c  l3dss1.c
+1882de8bea921b9ccd98fbe77267aa04  l3_1tr6.c
+3bd7af3a11693d028300278744d0da09  elsa.c
+# end of md5sums
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3i
+Charset: noconv
+
+iQCVAwUBNrl5JDpxHvX/mS9tAQHm8wP+Nk64UJ2abdDG/igXZSrwcYhX/Kp7cxt9
+ccYp+aaur+pALA0lxwY3xcLt9u36fCYuTLHAVmQoiC9Vbemj37yzM2rUpz9nkw/7
+D6gLqZs2jxVpAwVVJgp0JwDONKXaRX6Lt2EPD9PTW6vxRWEu0HqGhM5hrtd/o4rV
+mC1W7Wj13XM=
+=LdhT
+-----END PGP SIGNATURE-----
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/mic.c linux/drivers/isdn/hisax/mic.c
--- v2.3.3/linux/drivers/isdn/hisax/mic.c	Wed Apr  1 16:21:02 1998
+++ linux/drivers/isdn/hisax/mic.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: mic.c,v 1.6 1998/02/17 15:39:57 keil Exp $
+/* $Id: mic.c,v 1.7 1998/04/15 16:44:32 keil Exp $
X 
X  * mic.c  low level stuff for mic cards
X  *
@@ -8,6 +8,9 @@
X  *
X  *
X  * $Log: mic.c,v $
+ * Revision 1.7  1998/04/15 16:44:32  keil
+ * new init code
+ *
X  * Revision 1.6  1998/02/17 15:39:57  keil
X  * fix reset problem
X  *
@@ -37,7 +40,7 @@
X 
X extern const char *CardType[];
X 
-const char *mic_revision = "$Revision: 1.6 $";
+const char *mic_revision = "$Revision: 1.7 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -220,10 +223,7 @@
X 					I4L_IRQ_FLAG, "HiSax", cs));
X 		case CARD_INIT:
X inithscx(cs); /* /RTSA := ISAC RST */
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c
--- v2.3.3/linux/drivers/isdn/hisax/netjet.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/hisax/netjet.c	Sun May 23 10:03:41 1999
@@ -1,13 +1,30 @@
-/* $Id: netjet.c,v 1.3 1998/02/12 23:08:05 keil Exp $
+/* $Id: netjet.c,v 1.8 1998/11/15 23:55:14 keil Exp $
X 
X  * netjet.c     low level stuff for Traverse Technologie NETJet ISDN cards
X  *
- * Author     Karsten Keil (ke...@temic-ech.spacenet.de)
+ * Author     Karsten Keil (ke...@isdn4linux.de)
X  *
X  * Thanks to Traverse Technologie Australia for documents and informations
X  *
X  *
X  * $Log: netjet.c,v $
+ * Revision 1.8  1998/11/15 23:55:14  keil
+ * changes from 2.0
+ *
+ * Revision 1.7 1998/09/30 22:24:48 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6  1998/08/13 23:36:54  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5  1998/05/25 12:58:21  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.4 1998/04/15 16:42:35 keil
+ * new init code
+ * new PCI init (2.1.94)
+ *
X  * Revision 1.3  1998/02/12 23:08:05  keil
X  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
X  *
@@ -25,15 +42,12 @@
X #include "hscx.h"
X #include "isdnl1.h"
X #include <linux/pci.h>
-#include <linux/bios32.h>
X #include <linux/interrupt.h>
-#define fcstab  ppp_crc16_table
X #include <linux/ppp_defs.h>
-extern __u16 ppp_crc16_table[256]; /* from ppp code */
X 
X extern const char *CardType[];
X 
-const char *NETjet_revision = "$Revision: 1.3 $";
+const char *NETjet_revision = "$Revision: 1.8 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -62,6 +76,12 @@
X 
X #define NETJET_ISAC_OFF	0xc0
X #define NETJET_ISACIRQ	0x10
+#define NETJET_IRQM0_READ	0x0c
+#define NETJET_IRQM0_READ_1	0x04
+#define NETJET_IRQM0_READ_2	0x08
+#define NETJET_IRQM0_WRITE	0x03
+#define NETJET_IRQM0_WRITE_1	0x01
+#define NETJET_IRQM0_WRITE_2	0x02
X 
X #define NETJET_DMA_SIZE 512
X 
@@ -115,6 +135,42 @@
X 	insb(cs->hw.njet.isac, data, size);
X }
X 
+__u16 fcstab[256] =
+{
+	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
X static void 
X WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
X {
@@ -146,25 +202,20 @@
X mode_tiger(struct BCState *bcs, int mode, int bc)
X {
X 	struct IsdnCardState *cs = bcs->cs;
-	char tmp[64];
X 
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "Tiger mode %d bchan %d/%d",
+	if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "Tiger mode %d bchan %d/%d",
X 			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
X 	bcs->mode = mode;
X bcs->channel = bc;
X 	switch (mode) {
X 		case (L1_MODE_NULL):
X 			fill_mem(bcs, bcs->hw.tiger.send,
X 				NETJET_DMA_SIZE, bc, 0xff);
-			if (cs->debug & L1_DEB_HSCX) {
-				sprintf(tmp, "Tiger stat rec %d/%d send %d",
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "Tiger stat rec %d/%d send %d",
X 					bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err,
X 					bcs->hw.tiger.s_tot); 
-				debugl1(cs, tmp);
-			}
X 			if ((cs->bcs[0].mode == L1_MODE_NULL) &&
X 				(cs->bcs[1].mode == L1_MODE_NULL)) {
X 				cs->hw.njet.dmactrl = 0;
@@ -197,16 +248,14 @@
X 			test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
X 			break;
X 	}
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "tiger: set %x %x %x  %x/%x  pulse=%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "tiger: set %x %x %x  %x/%x  pulse=%d",
X 			bytein(cs->hw.njet.base + NETJET_DMACTRL),
X 			bytein(cs->hw.njet.base + NETJET_IRQMASK0),
X 			bytein(cs->hw.njet.base + NETJET_IRQSTAT0),
X 			inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
X 			inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
X 			bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-		debugl1(cs, tmp);
-	}
X }
X 
X static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
@@ -266,7 +315,7 @@
X 			val >>= 1;\
X 		}
X 
-static void make_raw_data(struct BCState *bcs) {
+static int make_raw_data(struct BCState *bcs) {
X 	register u_int i,s_cnt=0;
X 	register u_char j;
X 	register u_char val;
@@ -274,13 +323,15 @@
X 	register u_char s_val = 0;
X 	register u_char bitcnt = 0;
X 	u_int fcs;
-	char tmp[64];
-	
X 	
+	if (!bcs->tx_skb) {
+		debugl1(bcs->cs, "tiger make_raw: NULL skb");
+		return(1);
+	}
X 	bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE;
X 	fcs = PPP_INITFCS;
-	for (i=0; i<bcs->hw.tiger.tx_skb->len; i++) {
-		val = bcs->hw.tiger.tx_skb->data[i];
+	for (i=0; i<bcs->tx_skb->len; i++) {
+		val = bcs->tx_skb->data[i];
X 		fcs = PPP_FCS (fcs, val);
X 		MAKE_RAW_BYTE;
X 	}
@@ -303,11 +354,9 @@
X 		}
X 		val >>= 1;
X 	}
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger make_raw: in %d out %d.%d",
-			bcs->hw.tiger.tx_skb->len, s_cnt, bitcnt);
-		debugl1(bcs->cs,tmp);
-	}
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d",
+			bcs->tx_skb->len, s_cnt, bitcnt);
X 	if (bitcnt) {
X 		while (8>bitcnt++) {
X 			s_val >>= 1;
@@ -316,8 +365,9 @@
X 		bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
X 	}
X 	bcs->hw.tiger.sendcnt = s_cnt;
-	bcs->tx_cnt -= bcs->hw.tiger.tx_skb->len;
+	bcs->tx_cnt -= bcs->tx_skb->len;
X 	bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
+	return(0);
X }
X 
X static void got_frame(struct BCState *bcs, int count) {
@@ -349,7 +399,6 @@
X 	register u_char r_val = bcs->hw.tiger.r_val;
X 	register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
X 	u_int *p = buf;
-	char tmp[64];
X         
X 	for (i=0;i<cnt;i++) {
X 		val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff);
@@ -370,11 +419,9 @@
X 				} else {
X 					r_one=0;
X 					state= HDLC_FLAG_SEARCH;
-					if (bcs->cs->debug & L1_DEB_HSCX) {
-						sprintf(tmp,"tiger read_raw: zBit(%d,%d,%d) %x",
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x",
X 							bcs->hw.tiger.r_tot,i,j,val);
-						debugl1(bcs->cs,tmp);
-					}
X 				}
X 			} else if (state == HDLC_FLAG_SEARCH) { 
X 				if (val & 1) {
@@ -387,11 +434,9 @@
X 						bitcnt=0;
X 						r_val=0;
X 						state=HDLC_FLAG_FOUND;
-						if (bcs->cs->debug & L1_DEB_HSCX) {
-							sprintf(tmp,"tiger read_raw: flag(%d,%d,%d) %x",
+						if (bcs->cs->debug & L1_DEB_HSCX)
+							debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x",
X 								bcs->hw.tiger.r_tot,i,j,val);
-							debugl1(bcs->cs,tmp);
-						}
X 					}
X 					r_one=0;
X 				}
@@ -425,12 +470,10 @@
X 					bcs->hw.tiger.r_fcs = PPP_INITFCS;
X 					bcs->hw.tiger.rcvbuf[0] = r_val;
X 					bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
-					if (bcs->cs->debug & L1_DEB_HSCX) {
-						sprintf(tmp,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
X 							bcs->hw.tiger.r_tot,i,j,r_val,val,
X 							bcs->cs->hw.njet.irqstat0);
-						debugl1(bcs->cs,tmp);
-					}
X 				}
X 			} else if (state ==  HDLC_FRAME_FOUND) {
X 				if (val & 1) {
@@ -453,11 +496,9 @@
X 							state=HDLC_FLAG_SEARCH;
X 							bcs->hw.tiger.r_err++;
X 						} else {
-							if (bcs->cs->debug & L1_DEB_HSCX) {
-								sprintf(tmp,"tiger frame end(%d,%d): fcs(%x) i %x",
+							if (bcs->cs->debug & L1_DEB_HSCX)
+								debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x",
X 									i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0);
-								debugl1(bcs->cs, tmp);
-							}
X 							if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) {
X 								got_frame(bcs, (bitcnt>>3)-3);
X 							} else
@@ -509,7 +550,15 @@
X 	u_int *p;
X 	int cnt = NETJET_DMA_SIZE/2;
X 	
-	if (cs->hw.njet.irqstat0 & 4)
+	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
+		debugl1(cs,"tiger warn read double dma %x/%x",
+			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+		return;
+	} else {
+		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ;
+		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ);
+	}	
+	if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1)
X 		p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1;
X 	else
X 		p = cs->bcs[0].hw.tiger.rec + cnt - 1;
@@ -517,32 +566,28 @@
X 		read_raw(cs->bcs, p, cnt);
X 	if (cs->bcs[1].mode == L1_MODE_HDLC)
X 		read_raw(cs->bcs + 1, p, cnt);
-	cs->hw.njet.irqstat0 &= 0xf3;
+	cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ;
X }
X 
X static void write_raw(struct BCState *bcs, u_int *buf, int cnt);
X 
X static void fill_dma(struct BCState *bcs)
X {
-	char tmp[64];
X 	register u_int *p, *sp;
X 	register int cnt;
X 
-	if (!bcs->hw.tiger.tx_skb)
+	if (!bcs->tx_skb)
X 		return;
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger fill_dma1: c%d %4x", bcs->channel,
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel,
X 			bcs->Flag);
-			debugl1(bcs->cs,tmp);
-	}
X 	if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
X 		return;
-	make_raw_data(bcs);
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger fill_dma2: c%d %4x", bcs->channel,
+	if (make_raw_data(bcs))
+		return;		
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
X 			bcs->Flag);
-			debugl1(bcs->cs,tmp);
-	}
X 	if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
X 		write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
X 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
@@ -582,17 +627,14 @@
X 		}
X 		write_raw(bcs, p, cnt);
X 	}
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger fill_dma3: c%d %4x", bcs->channel,
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel,
X 			bcs->Flag);
-		debugl1(bcs->cs,tmp);
-	}
X }
X 
X static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
X 	u_int mask, val, *p=buf;
X 	u_int i, s_cnt;
-	char tmp[64];
X         
X         if (cnt <= 0)
X         	return;
@@ -617,26 +659,23 @@
X 				p = bcs->hw.tiger.send;
X 		}
X 		bcs->hw.tiger.s_tot += s_cnt;
-		if (bcs->cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
-			(u_int)buf, (u_int)p, s_cnt, cnt, bcs->hw.tiger.sendcnt,
-			bcs->cs->hw.njet.irqstat0);
-			debugl1(bcs->cs,tmp);
-		}
+		if (bcs->cs->debug & L1_DEB_HSCX)
+			debugl1(bcs->cs,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
+				(u_int)buf, (u_int)p, s_cnt, cnt,
+				bcs->hw.tiger.sendcnt, bcs->cs->hw.njet.irqstat0);
X 		if (bcs->cs->debug & L1_DEB_HSCX_FIFO)
X 			printframe(bcs->cs, bcs->hw.tiger.sp, s_cnt, "snd");
X 		bcs->hw.tiger.sp += s_cnt;
X 		bcs->hw.tiger.sendp = p;
X 		if (!bcs->hw.tiger.sendcnt) {
-			if (!bcs->hw.tiger.tx_skb) {
-				sprintf(tmp,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
-				debugl1(bcs->cs, tmp);
+			if (!bcs->tx_skb) {
+				debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
X 			} else {
X 				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->hw.tiger.tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.tiger.tx_skb->len);
-				dev_kfree_skb(bcs->hw.tiger.tx_skb);
-				bcs->hw.tiger.tx_skb = NULL;
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
+ bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+				dev_kfree_skb(bcs->tx_skb);
+				bcs->tx_skb = NULL;
X 			}
X 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 			bcs->hw.tiger.free = cnt - s_cnt;
@@ -646,7 +685,7 @@
X 				test_and_clear_bit(BC_FLG_HALF, &bcs->Flag);
X 				test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag);
X 			}
-			if ((bcs->hw.tiger.tx_skb = skb_dequeue(&bcs->squeue))) {
+			if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
X 				fill_dma(bcs);
X 			} else {
X 				mask ^= 0xffffffff;
@@ -656,11 +695,9 @@
X 						if (p>bcs->hw.tiger.s_end)
X 							p = bcs->hw.tiger.send;
X 					}
-					if (bcs->cs->debug & L1_DEB_HSCX) {
-						sprintf(tmp, "tiger write_raw: fill rest %d",
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs, "tiger write_raw: fill rest %d",
X 							cnt - s_cnt);
-						debugl1(bcs->cs,tmp);
-					}
X 				}
X 				bcs->event |= 1 << B_XMTBUFREADY;
X 				queue_task(&bcs->tqueue, &tq_immediate);
@@ -671,24 +708,28 @@
X 		test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
X 		fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
X 		bcs->hw.tiger.free += cnt;
-		if (bcs->cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp,"tiger write_raw: fill half");
-			debugl1(bcs->cs,tmp);
-		}
+		if (bcs->cs->debug & L1_DEB_HSCX)
+			debugl1(bcs->cs,"tiger write_raw: fill half");
X 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
X 		test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
X 		fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
-		if (bcs->cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp,"tiger write_raw: fill full");
-			debugl1(bcs->cs,tmp);
-		}
+		if (bcs->cs->debug & L1_DEB_HSCX)
+			debugl1(bcs->cs,"tiger write_raw: fill full");
X 	}
X }
X 
X static void write_tiger(struct IsdnCardState *cs) {
X 	u_int *p, cnt = NETJET_DMA_SIZE/2;
X 	
-	if (cs->hw.njet.irqstat0  & 1)
+	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
+		debugl1(cs,"tiger warn write double dma %x/%x",
+			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+		return;
+	} else {
+		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE;
+		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE);
+	}	
+	if (cs->hw.njet.irqstat0  & NETJET_IRQM0_WRITE_1)
X 		p = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1;
X 	else
X 		p = cs->bcs[0].hw.tiger.send + cnt - 1;
@@ -696,7 +737,7 @@
X 		write_raw(cs->bcs, p, cnt);
X 	if (cs->bcs[1].mode == L1_MODE_HDLC)
X 		write_raw(cs->bcs + 1, p, cnt);
-	cs->hw.njet.irqstat0 &= 0xfc;
+	cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE;
X }
X 
X static void
@@ -706,45 +747,58 @@
X 	long flags;
X 
X 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
X 			save_flags(flags);
X 			cli();
- if (st->l1.bcs->hw.tiger.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
X 				skb_queue_tail(&st->l1.bcs->squeue, skb);
X 				restore_flags(flags);
X 			} else {
- st->l1.bcs->hw.tiger.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
X 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 				restore_flags(flags);
X 			}
X 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.tiger.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
X 				printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
X 				break;
X 			}
X 			save_flags(flags);
X 			cli();
-			st->l1.bcs->hw.tiger.tx_skb = skb;
+			st->l1.bcs->tx_skb = skb;
X 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
X 			restore_flags(flags);
X 			break;
-		case (PH_PULL_REQ):
- if (!st->l1.bcs->hw.tiger.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
X 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
X 			} else
X 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
X break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ mode_tiger(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
X 	}
X }
X 
+
X void
X close_tigerstate(struct BCState *bcs)
X {
-	struct sk_buff *skb;
-
-	mode_tiger(bcs, 0, 0);
+	mode_tiger(bcs, 0, bcs->channel);
X 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
X 		if (bcs->hw.tiger.rcvbuf) {
X 			kfree(bcs->hw.tiger.rcvbuf);
@@ -754,32 +808,26 @@
X 			kfree(bcs->hw.tiger.sendbuf);
X 			bcs->hw.tiger.sendbuf = NULL;
X 		}
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
- }
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-		if (bcs->hw.tiger.tx_skb) {
-			dev_kfree_skb(bcs->hw.tiger.tx_skb);
-			bcs->hw.tiger.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
X 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 		}
X 	}
X }
X 
X static int
-open_tigerstate(struct IsdnCardState *cs, int bc)
+open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs)
X {
-	struct BCState *bcs = cs->bcs + bc;
-
X 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_KERNEL))) {
+		if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
X 			printk(KERN_WARNING
X 			       "HiSax: No memory for tiger.rcvbuf\n");
X 			return (1);
X 		}
-		if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_KERNEL))) {
+		if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
X 			printk(KERN_WARNING
X 			       "HiSax: No memory for tiger.sendbuf\n");
X 			return (1);
@@ -787,7 +835,7 @@
X 		skb_queue_head_init(&bcs->rqueue);
X 		skb_queue_head_init(&bcs->squeue);
X 	}
- bcs->hw.tiger.tx_skb = NULL;
+	bcs->tx_skb = NULL;
X bcs->hw.tiger.sendcnt = 0;
X 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
X 	bcs->event = 0;
@@ -795,34 +843,17 @@
X 	return (0);
X }
X 
-static void
-tiger_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_tiger(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
X int
X setstack_tiger(struct PStack *st, struct BCState *bcs)
X {
-	if (open_tigerstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+ if (open_tigerstate(st->l1.hardware, bcs))
X 		return (-1);
X 	st->l1.bcs = bcs;
X 	st->l2.l2l1 = tiger_l2l1;
-	st->ma.manl1 = tiger_manl1;
X 	setstack_manager(st);
X 	bcs->st = st;
+	setstack_l1_B(st);
X 	return (0);
X }
X 
@@ -830,8 +861,6 @@
X __initfunc(void
X inittiger(struct IsdnCardState *cs))
X {
-	char tmp[128];
-
X 	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_SIZE * sizeof(unsigned int),
X 		GFP_KERNEL | GFP_DMA))) {
X 		printk(KERN_WARNING
@@ -845,9 +874,8 @@
X 	cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
X 	
X 	memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
-	sprintf(tmp, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
+	debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
X 		(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1));
-	debugl1(cs, tmp);
X 	outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
X 		cs->hw.njet.base + NETJET_DMA_READ_START);
X 	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
@@ -860,9 +888,8 @@
X 		       "HiSax: No memory for tiger.rec\n");
X 		return;
X 	}
-	sprintf(tmp, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
+	debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
X 		(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1));
-	debugl1(cs, tmp);
X 	cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
X 	memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
X 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
@@ -871,11 +898,10 @@
X 		cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
X 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1),
X 		cs->hw.njet.base + NETJET_DMA_WRITE_END);
-	sprintf(tmp, "tiger: dmacfg  %x/%x  pulse=%d",
+	debugl1(cs, "tiger: dmacfg  %x/%x  pulse=%d",
X 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
X 		inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
X 		bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-	debugl1(cs, tmp);
X 	cs->hw.njet.last_is0 = 0;
X 	cs->bcs[0].BC_SetStack = setstack_tiger;
X 	cs->bcs[1].BC_SetStack = setstack_tiger;
@@ -906,8 +932,8 @@
X netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs)
X {
X 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 1;
-	char tmp[128];
+	u_char val, sval;
+	long flags;
X 
X 	if (!cs) {
X 		printk(KERN_WARNING "NETjet: Spurious interrupt!\n");
@@ -916,49 +942,49 @@
X 	if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
X 		NETJET_ISACIRQ)) {
X 		val = ReadISAC(cs, ISAC_ISTA);
-		if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "tiger: i1 %x %x", sval, val);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "tiger: i1 %x %x", sval, val);
X 		if (val) {
X 			isac_interrupt(cs, val);
-			stat |= 2;
+			WriteISAC(cs, ISAC_MASK, 0xFF);
+			WriteISAC(cs, ISAC_MASK, 0x0);
X 		}
X 	}
-	if ((cs->hw.njet.irqstat0 = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
-/*		sprintf(tmp, "tiger: ist0 %x  %x %x  %x/%x  pulse=%d",
+	save_flags(flags);
+	cli();
+	if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
+		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			restore_flags(flags);
+			return;
+		}
+		cs->hw.njet.irqstat0 = sval;
+		restore_flags(flags);
+/*		debugl1(cs, "tiger: ist0 %x  %x %x  %x/%x  pulse=%d",
X 			sval, 
X 			bytein(cs->hw.njet.base + NETJET_DMACTRL),
X 			bytein(cs->hw.njet.base + NETJET_IRQMASK0),
X 			inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
X 			inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
X 			bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-		debugl1(cs, tmp);
X */
-		if (cs->hw.njet.last_is0 & cs->hw.njet.irqstat0 & 0xf) {
-			sprintf(tmp, "tiger: ist0 %x->%x irq lost",
-				cs->hw.njet.last_is0, cs->hw.njet.irqstat0);
-			debugl1(cs, tmp);
-		}
-		cs->hw.njet.last_is0 = cs->hw.njet.irqstat0;
X /*		cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30;
X */		byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0);
X /*		byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0);
-*/		if (cs->hw.njet.irqstat0 & 0x0c)
+*/		if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ)
X 			read_tiger(cs);
-		if (cs->hw.njet.irqstat0 & 0x03)
+		if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE)
X 			write_tiger(cs);
-	}
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		restore_flags(flags);
+
X /*	if (!testcnt--) {
X 		cs->hw.njet.dmactrl = 0;
X 		byteout(cs->hw.njet.base + NETJET_DMACTRL,
X 			cs->hw.njet.dmactrl);
X 		byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
X 	}
-*/	if (stat & 2) {
-		WriteISAC(cs, ISAC_MASK, 0xFF);
-		WriteISAC(cs, ISAC_MASK, 0x0);
-	}
+*/
X }
X 
X static void
@@ -1006,11 +1032,13 @@
X 			return(0);
X 		case CARD_SETIRQ:
X 			return(request_irq(cs->irq, &netjet_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
+					I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs));
X 		case CARD_INIT:
X 			inittiger(cs);
X 			clear_pending_isac_ints(cs);
X 			initisac(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
@@ -1020,7 +1048,7 @@
X 
X 
X 
-static 	int pci_index __initdata = 0;
+static 	struct pci_dev *dev_netjet __initdata = NULL;
X 
X __initfunc(int
X setup_netjet(struct IsdnCard *card))
@@ -1028,52 +1056,37 @@
X 	int bytecnt;
X 	struct IsdnCardState *cs = card->cs;
X 	char tmp[64];
-#if CONFIG_PCI
-	u_char pci_bus, pci_device_fn, pci_irq;
-	u_int pci_ioaddr, found;
-#endif
X 
X 	strcpy(tmp, NETjet_revision);
X 	printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp));
X 	if (cs->typ != ISDN_CTYPE_NETJET)
X 		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
X #if CONFIG_PCI
-	found = 0;
-	for (; pci_index < 0xff; pci_index++) {
-		if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH,
-			PCI_NETJET_ID, pci_index, &pci_bus, &pci_device_fn)
-			== PCIBIOS_SUCCESSFUL)
-			found = 1;
-		else
-			break;
-		/* get IRQ */
-		pcibios_read_config_byte(pci_bus, pci_device_fn,
-			PCI_INTERRUPT_LINE, &pci_irq);
-
-		/* get IO address */
-		pcibios_read_config_dword(pci_bus, pci_device_fn,
-			PCI_BASE_ADDRESS_0, &pci_ioaddr);
-		if (found)
-			break;
-	}
-	if (!found) {
-		printk(KERN_WARNING "NETjet: No PCI card found\n");
+	if (!pci_present()) {
+		printk(KERN_ERR "Netjet: no PCI bus present\n");
X 		return(0);
X 	}
-	if (!pci_irq) {
+	if ((dev_netjet = pci_find_device(PCI_VENDOR_TRAVERSE_TECH,
+		PCI_NETJET_ID,  dev_netjet))) {
+		cs->irq = dev_netjet->irq;
+		if (!cs->irq) {
X 		printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
X 		return(0);
X 	}
-	if (!pci_ioaddr) {
+		cs->hw.njet.base = dev_netjet->base_address[0] &
+			PCI_BASE_ADDRESS_IO_MASK; 
+		if (!cs->hw.njet.base) {
X 		printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
X 		return(0);
X 	}
-	pci_ioaddr &= ~3; /* remove io/mem flag */
-	cs->hw.njet.base = pci_ioaddr; 
-	cs->hw.njet.auxa = pci_ioaddr + NETJET_AUXDATA;
-	cs->hw.njet.isac = pci_ioaddr | NETJET_ISAC_OFF;
-	cs->irq = pci_irq;
+		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
X 	bytecnt = 256;
+	} else {
+		printk(KERN_WARNING "NETjet: No PCI card found\n");
+		return(0);
+	}
X #else
X 	printk(KERN_WARNING "NETjet: NO_PCI_BIOS\n");
X 	printk(KERN_WARNING "NETjet: unable to config NETJET PCI\n");
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/niccy.c linux/drivers/isdn/hisax/niccy.c
--- v2.3.3/linux/drivers/isdn/hisax/niccy.c	Tue Apr  7 07:52:04 1998
+++ linux/drivers/isdn/hisax/niccy.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.2 1998/02/11 17:31:04 keil Exp $
+/* $Id: niccy.c,v 1.4 1998/04/16 19:16:48 keil Exp $
X 
X  * niccy.c  low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
X  *          compatible (SAGEM cybermodem)
@@ -8,24 +8,28 @@
X  * Thanks to Dr. Neuhaus and SAGEM for informations
X  *
X  * $Log: niccy.c,v $
- * Revision 1.2  1998/02/11 17:31:04  keil
- * new file
+ * Revision 1.4  1998/04/16 19:16:48  keil
+ * need config.h
X  *
+ * Revision 1.3  1998/04/15 16:42:59  keil
+ * new init code
X  *
+ * Revision 1.2  1998/02/11 17:31:04  keil
+ * new file
X  *
X  */
X 
-#include <linux/config.h>
+
X #define __NO_VERSION__
+#include <linux/config.h>
X #include "hisax.h"
X #include "isac.h"
X #include "hscx.h"
X #include "isdnl1.h"
X #include <linux/pci.h>
-#include <linux/bios32.h>
X 
X extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.2 $";
+const char *niccy_revision = "$Revision: 1.4 $";
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
@@ -44,6 +48,10 @@
X /* PCI stuff */
X #define PCI_VENDOR_DR_NEUHAUS	0x1267
X #define PCI_NICCY_ID		0x1016
+#define PCI_IRQ_CTRL_REG	0x38
+#define PCI_IRQ_ENABLE		0x1f00
+#define PCI_IRQ_DISABLE		0xff0000
+#define PCI_IRQ_ASSERT		0x800000
X 
X static inline u_char
X readreg(unsigned int ale, unsigned int adr, u_char off)
@@ -152,6 +160,13 @@
X 		printk(KERN_WARNING "Niccy: Spurious interrupt!\n");
X 		return;
X 	}
+	if (cs->subtyp == NICCY_PCI) {
+		int ival;
+		ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */
+			return;
+		outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+	}
X 	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
X       Start_HSCX:
X 	if (val) {
@@ -191,9 +206,15 @@
X void
X release_io_niccy(struct IsdnCardState *cs)
X {
-	if (cs->subtyp == NICCY_PCI)
+	if (cs->subtyp == NICCY_PCI) {
+		int val;
+		
+		val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		val &= PCI_IRQ_DISABLE;
+		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		release_region(cs->hw.niccy.cfg_reg, 0x80);
X 		release_region(cs->hw.niccy.isac, 4);
-	else {
+	} else {
X 		release_region(cs->hw.niccy.isac, 2);
X 		release_region(cs->hw.niccy.isac_ale, 2);
X 	}
@@ -202,12 +223,20 @@
X static void
X niccy_reset(struct IsdnCardState *cs)
X {
-	// No reset procedure known
+	int val, nval;
+	
+	val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+	nval = val | PCI_IRQ_ENABLE;
+	outl(nval, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+
+	inithscxisac(cs, 3);
X }
X 
X static int
X niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
X {
+	int imode;
+	
X 	switch (mt) {
X 		case CARD_RESET:
X 			niccy_reset(cs);
@@ -216,13 +245,15 @@
X 			release_io_niccy(cs);
X 			return(0);
X 		case CARD_SETIRQ:
+			if (cs->subtyp == NICCY_PCI)
+				imode = I4L_IRQ_FLAG | SA_SHIRQ;
+			else
+				imode = I4L_IRQ_FLAG;
X 			return(request_irq(cs->irq, &niccy_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
+				imode, "HiSax", cs));
+			break;
X 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+ niccy_reset(cs);
X 			return(0);
X 		case CARD_TEST:
X 			return(0);
@@ -230,7 +261,7 @@
X 	return(0);
X }
X 
-static 	int pci_index __initdata = 0;
+static 	struct pci_dev *niccy_dev __initdata = NULL;
X 
X __initfunc(int
X setup_niccy(struct IsdnCard *card))
@@ -272,49 +303,41 @@
X 			request_region(cs->hw.niccy.isac_ale, 2, "niccy addr");
X 	} else {
X #if CONFIG_PCI
-		u_char pci_bus, pci_device_fn, pci_irq;
X 		u_int pci_ioaddr;
X 
+		if (!pci_present()) {
+			printk(KERN_ERR "Niccy: no PCI bus present\n");
+			return(0);
+		}
+
X 		cs->subtyp = 0;
-		for (; pci_index < 0xff; pci_index++) {
-			if (pcibios_find_device(PCI_VENDOR_DR_NEUHAUS,
-			   PCI_NICCY_ID, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-				cs->subtyp = NICCY_PCI;
-			else
-				break;
+		if ((niccy_dev = pci_find_device(PCI_VENDOR_DR_NEUHAUS,
+			   PCI_NICCY_ID, niccy_dev))) {
X 			/* get IRQ */
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &pci_irq);
-
-			/* get IO address */
-			/* if it won't work try the other PCI addresses
-			 * PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5
-			 */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_2, &pci_ioaddr);
-			if (cs->subtyp)
-				break;
-		}
-		if (!cs->subtyp) {
-			printk(KERN_WARNING "Niccy: No PCI card found\n");
+			if (!niccy_dev->irq) {
+				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
X 			return(0);
X 		}
-		if (!pci_irq) {
-			printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
+			cs->irq = niccy_dev->irq;
+			if (!niccy_dev->base_address[0]) {
+				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
X 			return(0);
X 		}
-
-		if (!pci_ioaddr) {
+			cs->hw.niccy.cfg_reg = niccy_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+			if (!niccy_dev->base_address[1]) {
X 			printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
X 			return(0);
X 		}
-		pci_ioaddr &= ~3; /* remove io/mem flag */
+			pci_ioaddr = niccy_dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
X 		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
X 		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
X 		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
X 		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-		cs->irq = pci_irq;
+			cs->subtyp = NICCY_PCI;
+		} else {
+			printk(KERN_WARNING "Niccy: No PCI card found\n");
+			return(0);
+		}
X 		if (check_region((cs->hw.niccy.isac), 4)) {
X 			printk(KERN_WARNING
X 				"HiSax: %s data port %x-%x already in use\n",
@@ -324,6 +347,17 @@
X 			return (0);
X 		} else
X 			request_region(cs->hw.niccy.isac, 4, "niccy");
+		if (check_region(cs->hw.niccy.cfg_reg, 0x80)) {
+			printk(KERN_WARNING
+			       "HiSax: %s pci port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.niccy.cfg_reg,
+				cs->hw.niccy.cfg_reg + 0x80);
+			release_region(cs->hw.niccy.isac, 4);
+			return (0);
+		} else {
+			request_region(cs->hw.niccy.cfg_reg, 0x80, "niccy pci");
+		}
X #else
X 		printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
X 		printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
@@ -334,7 +368,6 @@
X 		"HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
X 		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
X 		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	niccy_reset(cs);
X 	cs->readisac = &ReadISAC;
X 	cs->writeisac = &WriteISAC;
X 	cs->readisacfifo = &ReadISACfifo;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/q931.c linux/drivers/isdn/hisax/q931.c
--- v2.3.3/linux/drivers/isdn/hisax/q931.c	Wed Apr  1 16:21:02 1998
+++ linux/drivers/isdn/hisax/q931.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: q931.c,v 1.6 1997/07/27 21:09:44 keil Exp $
+/* $Id: q931.c,v 1.7 1998/11/15 23:55:17 keil Exp $
X 
X  * q931.c       code to decode ITU Q.931 call control messages
X  *
@@ -14,6 +14,9 @@
X  *
X  *
X  * $Log: q931.c,v $
+ * Revision 1.7  1998/11/15 23:55:17  keil
+ * changes from 2.0
+ *
X  * Revision 1.6  1997/07/27 21:09:44  keil
X  * move functions to isdnl3.c
X  *
@@ -159,7 +162,7 @@
X 	{MT_N0_CLO_ACK, "CLOse ACKnowledge"}
X };
X 
-int mt_n0_len = (sizeof(mt_n0) / sizeof(struct MessageType));
+#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
X 
X static
X struct MessageType mt_n1[] =
@@ -196,7 +199,7 @@
X 	{MT_N1_STAT, "STATus"}
X };
X 
-int mt_n1_len = (sizeof(mt_n1) / sizeof(struct MessageType));
+#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
X 
X static struct MessageType fac_1tr6[] =
X {
@@ -220,9 +223,7 @@
X 	{FAC_Rueckwechsel, "Rueckwechsel"},
X 	{FAC_Umleitung, "Umleitung"}
X };
-int fac_1tr6_len = (sizeof(fac_1tr6) / sizeof(struct MessageType));
-
-
+#define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType))
X 
X static int
X prbits(char *dest, u_char b, int start, int len)
@@ -925,7 +926,7 @@
X 	{WE0_userInfo, "User Info", general}
X };
X 
-static int we_0_len = (sizeof(we_0) / sizeof(struct InformationElement));
+#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
X 
X static struct InformationElement we_6[] =
X {
@@ -937,7 +938,7 @@
X 	{WE6_statusCalled, "Status Called", general},
X 	{WE6_addTransAttr, "Additional Transmission Attributes", general}
X };
-static int we_6_len = (sizeof(we_6) / sizeof(struct InformationElement));
+#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
X 
X int
X QuickHex(char *txt, u_char * p, int cnt)
@@ -964,39 +965,92 @@
X }
X 
X void
-LogFrame(struct IsdnCardState *sp, u_char * buf, int size)
+LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
X {
X 	char *dp;
X 
X 	if (size < 1)
X 		return;
-	dp = sp->dlogspace;
-	if (size < 4096 / 3 - 10) {
-		dp += sprintf(dp, "HEX:");
+	dp = cs->dlog;
+	if (size < MAX_DLOG_SPACE / 3 - 10) {
+		*dp++ = 'H';
+		*dp++ = 'E';
+		*dp++ = 'X';
+		*dp++ = ':';
X 		dp += QuickHex(dp, buf, size);
X 		dp--;
X 		*dp++ = '\n';
X 		*dp = 0;
+		HiSax_putstatus(cs, NULL, cs->dlog);
X 	} else
-		sprintf(dp, "LogFrame: warning Frame too big (%d)\n",
-			size);
-	HiSax_putstatus(sp, sp->dlogspace);
+		HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
X }
X 
X void
-dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
+dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
X {
-	u_char *bend = buf + size;
+	u_char *bend, *buf;
X 	char *dp;
X 	unsigned char pd, cr_l, cr, mt;
-	int i, cs = 0, cs_old = 0, cs_fest = 0;
+	unsigned char sapi, tei, ftyp;
+	int i, cset = 0, cs_old = 0, cs_fest = 0;
+	int size, finish = 0;
X 
-	if (size < 1)
+	if (skb->len < 3)
X 		return;
X 	/* display header */
-	dp = sp->dlogspace;
-	dp += sprintf(dp, "%s\n", comment);
-
+	dp = cs->dlog;
+	dp += jiftime(dp, jiffies);
+	*dp++ = ' ';
+	sapi = skb->data[0] >> 2;
+	tei  = skb->data[1] >> 1;
+	ftyp = skb->data[2];
+	buf = skb->data;
+	dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
+	size = skb->len;
+	
+	if (tei == GROUP_TEI) {
+		if (sapi == CTRL_SAPI) { /* sapi 0 */
+			if (ftyp == 3) {
+				dp += sprintf(dp, "broadcast\n");
+				buf += 3;
+				size -= 3;
+			} else {
+				dp += sprintf(dp, "no UI broadcast\n");
+				finish = 1;
+			}
+		} else if (sapi == TEI_SAPI) {
+			dp += sprintf(dp, "tei managment\n");
+			finish = 1;
+		} else {
+			dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi);
+			finish = 1;
+		}
+	} else {
+		if (sapi == CTRL_SAPI) {
+			if (!(ftyp & 1)) { /* IFrame */
+				dp += sprintf(dp, "with tei %d\n", tei);
+				buf += 4;
+				size -= 4;
+			} else {
+				dp += sprintf(dp, "SFrame with tei %d\n", tei);
+				finish = 1;
+			}
+		} else {
+			dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei);
+			finish = 1;
+		}
+	}
+	bend = skb->data + skb->len;
+	if (buf >= bend) {
+		dp += sprintf(dp, "frame too short\n");
+		finish = 1;
+	}
+	if (finish) {
+		*dp = 0;
+		HiSax_putstatus(cs, NULL, cs->dlog);
+		return;
+	}
X 	if ((0xfe & buf[0]) == PROTO_DIS_N0) {	/* 1TR6 */
X 		/* locate message type */
X 		pd = *buf++;
@@ -1007,11 +1061,11 @@
X 			cr = 0;
X 		mt = *buf++;
X 		if (pd == PROTO_DIS_N0) {	/* N0 */
-			for (i = 0; i < mt_n0_len; i++)
+			for (i = 0; i < MT_N0_LEN; i++)
X 				if (mt_n0[i].nr == mt)
X 					break;
X 			/* display message type if it exists */
-			if (i == mt_n0_len)
+			if (i == MT_N0_LEN)
X 				dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n",
X 					      cr & 0x7f, (cr & 0x80) ? "called" : "caller",
X 					      size, mt);
@@ -1020,11 +1074,11 @@
X 					      cr & 0x7f, (cr & 0x80) ? "called" : "caller",
X 					      size, mt_n0[i].descr);
X 		} else {	/* N1 */
-			for (i = 0; i < mt_n1_len; i++)
+			for (i = 0; i < MT_N1_LEN; i++)
X 				if (mt_n1[i].nr == mt)
X 					break;
X 			/* display message type if it exists */
-			if (i == mt_n1_len)
+			if (i == MT_N1_LEN)
X 				dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n",
X 					      cr & 0x7f, (cr & 0x80) ? "called" : "caller",
X 					      size, mt);
@@ -1041,8 +1095,8 @@
X 				switch ((*buf >> 4) & 7) {
X 					case 1:
X 						dp += sprintf(dp, "  Shift %x\n", *buf & 0xf);
-						cs_old = cs;
-						cs = *buf & 7;
+						cs_old = cset;
+						cset = *buf & 7;
X 						cs_fest = *buf & 8;
X 						break;
X 					case 3:
@@ -1066,33 +1120,33 @@
X 				continue;
X 			}
X 			/* No, locate it in the table */
-			if (cs == 0) {
-				for (i = 0; i < we_0_len; i++)
+			if (cset == 0) {
+				for (i = 0; i < WE_0_LEN; i++)
X 					if (*buf == we_0[i].nr)
X 						break;
X 
X 				/* When found, give appropriate msg */
-				if (i != we_0_len) {
+				if (i != WE_0_LEN) {
X 					dp += sprintf(dp, "  %s\n", we_0[i].descr);
X 					dp += we_0[i].f(dp, buf);
X 				} else
-					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
-			} else if (cs == 6) {
-				for (i = 0; i < we_6_len; i++)
+					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
+			} else if (cset == 6) {
+				for (i = 0; i < WE_6_LEN; i++)
X 					if (*buf == we_6[i].nr)
X 						break;
X 
X 				/* When found, give appropriate msg */
-				if (i != we_6_len) {
+				if (i != WE_6_LEN) {
X 					dp += sprintf(dp, "  %s\n", we_6[i].descr);
X 					dp += we_6[i].f(dp, buf);
X 				} else
-					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
+					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
X 			} else
-				dp += sprintf(dp, "  Unknown Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
+				dp += sprintf(dp, "  Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
X 			/* Skip to next element */
X 			if (cs_fest == 8) {
-				cs = cs_old;
+				cset = cs_old;
X 				cs_old = 0;
X 				cs_fest = 0;
X 			}
@@ -1170,6 +1224,6 @@
X 	} else {
X 		dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
X 	}
-	dp += sprintf(dp, "\n");
-	HiSax_putstatus(sp, sp->dlogspace);
+	*dp = 0;
+	HiSax_putstatus(cs, NULL, cs->dlog);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/rawhdlc.c linux/drivers/isdn/hisax/rawhdlc.c
--- v2.3.3/linux/drivers/isdn/hisax/rawhdlc.c	Wed May 20 18:54:37 1998
+++ linux/drivers/isdn/hisax/rawhdlc.c	Sun May 23 10:03:41 1999
@@ -1,4 +1,4 @@
-/* $Id: rawhdlc.c,v 1.2 1998/02/09 10:53:51 keil Exp $
+/* $Id: rawhdlc.c,v 1.3 1998/06/17 19:51:21 he Exp $
X 
X  * rawhdlc.c     support routines for cards that don't support HDLC
X  *
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/s0box.c linux/drivers/isdn/hisax/s0box.c
--- v2.3.3/linux/drivers/isdn/hisax/s0box.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/s0box.c	Sun May 23 10:03:41 1999
@@ -0,0 +1,277 @@
+/* $Id: s0box.c,v 2.1 1998/04/15 16:38:24 keil Exp $
+
+ * s0box.c      low level stuff for Creatix S0BOX
+ *
+ * Author       S0BOX specific stuff: Enrik Berkhan (en...@starfleet.inka.de)
+ *
+ *
+ */
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+const char *s0box_revision = "$Revision: 2.1 $";
+
+static inline void
+writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	outb_p(0x1c,padr+2);
+	outb_p(0x14,padr+2);
+	outb_p((addr+off)&0x7f,padr);
+	outb_p(0x16,padr+2);
+	outb_p(val,padr);
+	outb_p(0x17,padr+2);
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	restore_flags(flags);
+}
+
+static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
+			 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ;
+
+static inline u_char
+readreg(unsigned int padr, signed int addr, u_char off) {
+	register u_char n1, n2;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	outb_p(0x1c,padr+2);
+	outb_p(0x14,padr+2);
+	outb_p((addr+off)|0x80,padr);
+	outb_p(0x16,padr+2);
+	outb_p(0x17,padr+2);
+	n1 = (inb_p(padr+1) >> 3) & 0x17;
+	outb_p(0x16,padr+2);
+	n2 = (inb_p(padr+1) >> 3) & 0x17;
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	restore_flags(flags);
+	return nibtab[n1] | (nibtab[n2] << 4);
+}
+
+static inline void
+read_fifo(unsigned int padr, signed int adr, u_char * data, int size)
+{
+	int i;
+	register u_char n1, n2;
+	
+	outb_p(0x1c, padr+2);
+	outb_p(0x14, padr+2);
+	outb_p(adr|0x80, padr);
+	outb_p(0x16, padr+2);
+	for (i=0; i<size; i++) {
+		outb_p(0x17, padr+2);
+		n1 = (inb_p(padr+1) >> 3) & 0x17;
+		outb_p(0x16,padr+2);
+		n2 = (inb_p(padr+1) >> 3) & 0x17;
+		*(data++)=nibtab[n1] | (nibtab[n2] << 4);
+	}
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	return;
+}
+
+static inline void
+write_fifo(unsigned int padr, signed int adr, u_char * data, int size)
+{
+	int i;
+	outb_p(0x1c, padr+2);
+	outb_p(0x14, padr+2);
+	outb_p(adr&0x7f, padr);
+	for (i=0; i<size; i++) {
+		outb_p(0x16, padr+2);
+		outb_p(*(data++), padr);
+		outb_p(0x17, padr+2);
+	}
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	return;
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+ return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+ read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+ write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+ return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+ writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg)
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 20
+	struct IsdnCardState *cs = dev_id;
+	u_char val, stat = 0;
+	int count = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "Teles: Spurious interrupt!\n");
+		return;
+	}
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
+      Start_HSCX:
+	if (val) {
+		hscx_int_main(cs, val);
+		stat |= 1;
+	}
+ val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val) {
+		isac_interrupt(cs, val);
+		stat |= 2;
+	}
+	count++;
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (count >= MAXCOUNT)
+		printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
+	if (stat & 1) {
+		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
+	}
+	if (stat & 2) {
+		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+		writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	}
+}
+
+void
+release_io_s0box(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.teles3.cfg_reg, 8);
+}
+
+static int
+S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			break;
+		case CARD_RELEASE:
+			release_io_s0box(cs);
+			break;
+		case CARD_SETIRQ:
+			return(request_irq(cs->irq, &s0box_interrupt,
+					I4L_IRQ_FLAG, "HiSax", cs));
+		case CARD_INIT:
+			inithscxisac(cs, 3);
+			break;
+		case CARD_TEST:
+			break;
+	}
+	return(0);
+}
+
+__initfunc(int
+setup_s0box(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, s0box_revision);
+	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_S0BOX)
+		return (0);
+
+	cs->hw.teles3.cfg_reg = card->para[1];
+	cs->hw.teles3.hscx[0] = -0x20;
+	cs->hw.teles3.hscx[1] = 0x0;
+	cs->hw.teles3.isac = 0x20;
+	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
+	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
+	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+	cs->irq = card->para[0];
+	if (check_region(cs->hw.teles3.cfg_reg,8)) {
+		printk(KERN_WARNING
+		       "HiSax: %s ports %x-%x already in use\n",
+		       CardType[cs->typ],
+                       cs->hw.teles3.cfg_reg,
+                       cs->hw.teles3.cfg_reg + 7);
+		return 0;
+	} else
+		request_region(cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O");
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
+	printk(KERN_INFO
+	       "HiSax: hscx A:0x%x  hscx B:0x%x\n",
+	       cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &S0Box_card_msg;
+	ISACVersion(cs, "S0Box:");
+	if (HscxVersion(cs, "S0Box:")) {
+		printk(KERN_WARNING
+		       "S0Box: wrong HSCX versions check IO address\n");
+		release_io_s0box(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/sedlbauer.c linux/drivers/isdn/hisax/sedlbauer.c
--- v2.3.3/linux/drivers/isdn/hisax/sedlbauer.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/hisax/sedlbauer.c	Sun May 23 10:03:41 1999
@@ -1,11 +1,14 @@
-/* $Id: sedlbauer.c,v 1.6 1998/02/09 18:46:06 keil Exp $
+/* $Id: sedlbauer.c,v 1.9 1998/11/15 23:55:20 keil Exp $
X 
X  * sedlbauer.c  low level stuff for Sedlbauer cards
- *              includes Support for the Sedlbauer Speed Star 
- *              derived from the original file dynalink.c from Karsten Keil
+ *              includes support for the Sedlbauer speed star (speed star II),
+ *              support for the Sedlbauer speed fax+,
+ *              support for the Sedlbauer ISDN-Controller PC/104 and
+ *              support for the Sedlbauer speed pci
+ *              derived from the original file asuscom.c from Karsten Keil
X  *
X  * Copyright (C) 1997,1998 Marcus Niemann (for the modifications to
- *                                         the original file dynalink.c)
+ *                                         the original file asuscom.c)
X  *
X  * Author     Marcus Niemann (nie...@www-bib.fh-bielefeld.de)
X  *
@@ -14,6 +17,15 @@
X  *            Edgar Toernig
X  *
X  * $Log: sedlbauer.c,v $
+ * Revision 1.9  1998/11/15 23:55:20  keil
+ * changes from 2.0
+ *
+ * Revision 1.8  1998/08/13 23:34:51  keil
+ * starting speedfax+ (ISAR) support
+ *
+ * Revision 1.7  1998/04/15 16:44:33  keil
+ * new init code
+ *
X  * Revision 1.6  1998/02/09 18:46:06  keil
X  * Support for Sedlbauer PCMCIA (Marcus Niemann)
X  *
@@ -35,36 +47,91 @@
X  *
X  */
X 
+/* Supported cards:
+ * Card:	Chip:		Configuration:	Comment:
+ * ---------------------------------------------------------------------
+ * Speed Card	ISAC_HSCX	DIP-SWITCH
+ * Speed Win	ISAC_HSCX	ISAPNP
+ * Speed Fax+	ISAC_ISAR	ISAPNP		#HDLC works#
+ * Speed Star	ISAC_HSCX	CARDMGR
+ * Speed Win2	IPAC		ISAPNP
+ * ISDN PC/104	IPAC		DIP-SWITCH
+ * Speed Star2	IPAC		CARDMGR
+ * Speed PCI	IPAC		PNP		
+ *
+ * Important:
+ * For the sedlbauer speed fax+ to work properly you have to download 
+ * the firmware onto the card.
+ * For example: hisaxctrl <DriverID> 9 ISAR.BIN
+*/
+
+#define SEDLBAUER_PCI 1
+
X #define __NO_VERSION__
+#include <linux/config.h>
X #include "hisax.h"
X #include "isac.h"
+#include "ipac.h"
X #include "hscx.h"
+#include "isar.h"
X #include "isdnl1.h"
+#include <linux/pci.h>
X 
X extern const char *CardType[];
X 
-const char *Sedlbauer_revision = "$Revision: 1.6 $";
+const char *Sedlbauer_revision = "$Revision: 1.9 $";
X 
X const char *Sedlbauer_Types[] =
-{"None", "Speed Card", "Speed Win", "Speed Star"};
+	{"None", "speed card/win", "speed star", "speed fax+", 
+	"speed win II / ISDN PC/104", "speed star II", "speed pci"};
+
+#ifdef SEDLBAUER_PCI
+#define PCI_VENDOR_SEDLBAUER	0xe159
+#define PCI_SPEEDPCI_ID	0x02
+#endif
X  
-#define SEDL_SPEED_CARD 1
-#define SEDL_SPEED_WIN  2
-#define SEDL_SPEED_STAR 3
+#define SEDL_SPEED_CARD_WIN	1
+#define SEDL_SPEED_STAR 	2
+#define SEDL_SPEED_FAX		3
+#define SEDL_SPEED_WIN2_PC104 	4
+#define SEDL_SPEED_STAR2 	5
+#define SEDL_SPEED_PCI   	6
+
+#define SEDL_CHIP_TEST		0
+#define SEDL_CHIP_ISAC_HSCX	1
+#define SEDL_CHIP_ISAC_ISAR	2
+#define SEDL_CHIP_IPAC		3
+
+#define SEDL_BUS_ISA		1
+#define SEDL_BUS_PCI		2
+#define	SEDL_BUS_PCMCIA		3
X 
X #define byteout(addr,val) outb(val,addr)
X #define bytein(addr) inb(addr)
X 
-#define SEDL_RESET_ON	0
-#define SEDL_RESET_OFF	1
-#define SEDL_ISAC	2
-#define SEDL_HSCX	3
-#define SEDL_ADR	4
-
-#define SEDL_PCMCIA_RESET	0
-#define SEDL_PCMCIA_ISAC	1
-#define SEDL_PCMCIA_HSCX	2
-#define SEDL_PCMCIA_ADR		4
+#define SEDL_HSCX_ISA_RESET_ON	0
+#define SEDL_HSCX_ISA_RESET_OFF	1
+#define SEDL_HSCX_ISA_ISAC	2
+#define SEDL_HSCX_ISA_HSCX	3
+#define SEDL_HSCX_ISA_ADR	4
+
+#define SEDL_HSCX_PCMCIA_RESET	0
+#define SEDL_HSCX_PCMCIA_ISAC	1
+#define SEDL_HSCX_PCMCIA_HSCX	2
+#define SEDL_HSCX_PCMCIA_ADR	4
+
+#define SEDL_ISAR_ISA_ISAC		4
+#define SEDL_ISAR_ISA_ISAR		6
+#define SEDL_ISAR_ISA_ADR		8
+#define SEDL_ISAR_ISA_ISAR_RESET_ON	10
+#define SEDL_ISAR_ISA_ISAR_RESET_OFF	12
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 25'
echo 'File patch-2.3.4 is continued in part 26'
echo 26 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 27 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 27; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X 			}
X 			break;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h
--- v2.3.3/linux/drivers/isdn/icn/icn.h	Thu Jan  7 08:46:59 1999
+++ linux/drivers/isdn/icn/icn.h	Sun May 23 10:03:41 1999
@@ -318,9 +318,9 @@
X #ifdef MODULE
X MODULE_AUTHOR("Fritz Elfert");
X MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port address of first card");
+MODULE_PARM_DESC(portbase, "Port adress of first card");
X MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory address of all cards");
+MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
X MODULE_PARM(icn_id, "s");
X MODULE_PARM_DESC(icn_id, "ID-String of first card");
X MODULE_PARM(icn_id2, "s");
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_audio.c linux/drivers/isdn/isdn_audio.c
--- v2.3.3/linux/drivers/isdn/isdn_audio.c	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_audio.c	Sun May 23 10:03:42 1999
@@ -1,9 +1,10 @@
-/* $Id: isdn_audio.c,v 1.10 1998/02/20 17:09:40 fritz Exp $
+/* $Id: isdn_audio.c,v 1.13 1999/04/12 12:33:09 fritz Exp $
X 
X  * Linux ISDN subsystem, audio conversion and compression (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fr...@isdn4linux.de)
X  * DTMF code (c) 1996 by Christian Mock (c...@kukuruz.ping.at)
+ * Silence detection (c) 1998 by Armin Schindler (m...@gismo.telekom.de)
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
@@ -20,6 +21,15 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_audio.c,v $
+ * Revision 1.13  1999/04/12 12:33:09  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.12  1998/07/26 18:48:43  armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.11  1998/04/10 10:35:10  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
X  * Revision 1.10  1998/02/20 17:09:40  fritz
X  * Changes for recent kernels.
X  *
@@ -61,7 +71,7 @@
X #include "isdn_audio.h"
X #include "isdn_common.h"
X 
-char *isdn_audio_revision = "$Revision: 1.10 $";
+char *isdn_audio_revision = "$Revision: 1.13 $";
X 
X /*
X  * Misc. lookup-tables.
@@ -276,7 +286,7 @@
X isdn_audio_tlookup(const char *table, char *buff, unsigned long n)
X {
X 	while (n--)
-		*buff++ = table[*buff];
+		*buff++ = table[*(unsigned char *)buff];
X }
X #endif
X 
@@ -659,4 +669,93 @@
X 		}
X 		len -= c;
X 	}
+}
+
+silence_state *
+isdn_audio_silence_init(silence_state * s)
+{
+	if (!s)
+		s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
+	if (s) {
+		s->idx = 0;
+		s->state = 0;
+	}
+	return s;
+}
+
+void
+isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
+{
+	silence_state *s = info->silence_state;
+	int i;
+	signed char c;
+
+	if (!info->emu.vpar[1]) return;
+
+	for (i = 0; i < len; i++) {
+		if (fmt)
+		    c = isdn_audio_alaw_to_ulaw[*buf++];
+			else
+		    c = *buf++;
+
+		if (c > 0) c -= 128;
+		c = abs(c);
+
+		if (c > (info->emu.vpar[1] * 4)) { 
+			s->idx = 0;
+			s->state = 1; 
+		} else {
+			if (s->idx < 210000) s->idx++; 
+		}
+	}
+}
+
+void
+isdn_audio_eval_silence(modem_info * info)
+{
+	silence_state *s = info->silence_state;
+	struct sk_buff *skb;
+	unsigned long flags;
+	int di;
+	int ch;
+	char what;
+	char *p;
+
+	what = ' ';
+
+	if (s->idx > (info->emu.vpar[2] * 800)) { 
+		s->idx = 0;
+		if (!s->state) {	/* silence from beginning of rec */ 
+			what = 's';
+		} else {
+			what = 'q';
+		}
+	}
+		if ((what == 's') || (what == 'q')) {
+			printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
+				(what=='s') ? "silence":"quiet");
+			skb = dev_alloc_skb(2);
+			p = (char *) skb_put(skb, 2);
+			p[0] = 0x10;
+			p[1] = what;
+			if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
+				printk(KERN_WARNING
+				       "isdn_audio: insufficient skb_headroom, dropping\n");
+				kfree_skb(skb);
+				return;
+			}
+			ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+			ISDN_AUDIO_SKB_LOCK(skb) = 0;
+			save_flags(flags);
+			cli();
+			di = info->isdn_driver;
+			ch = info->isdn_channel;
+			__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
+			dev->drv[di]->rcvcount[ch] += 2;
+			restore_flags(flags);
+			/* Schedule dequeuing */
+			if ((dev->modempoll) && (info->rcvsched))
+				isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+			wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
+		} 
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_audio.h linux/drivers/isdn/isdn_audio.h
--- v2.3.3/linux/drivers/isdn/isdn_audio.h	Thu Feb 27 10:57:29 1997
+++ linux/drivers/isdn/isdn_audio.h	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_audio.h,v 1.5 1997/02/03 22:45:21 fritz Exp $
+/* $Id: isdn_audio.h,v 1.7 1999/04/12 12:33:11 fritz Exp $
X 
X  * Linux ISDN subsystem, audio conversion and compression (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fr...@isdn4linux.de)
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
@@ -19,6 +19,12 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_audio.h,v $
+ * Revision 1.7  1999/04/12 12:33:11  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.6  1998/07/26 18:48:44  armin
+ * Added silence detection in voice receive mode.
+ *
X  * Revision 1.5  1997/02/03 22:45:21  fritz
X  * Reformatted according CodingStyle
X  *
@@ -51,6 +57,11 @@
X 	int buf[DTMF_NPOINTS];
X } dtmf_state;
X 
+typedef struct silence_state {
+	int state;
+	unsigned int idx;
+} silence_state;
+
X extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long);
X extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
X extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
@@ -60,3 +71,6 @@
X extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
X extern void isdn_audio_eval_dtmf(modem_info *);
X dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
+extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
+extern void isdn_audio_eval_silence(modem_info *);
+silence_state *isdn_audio_silence_init(silence_state *);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_bsdcomp.c linux/drivers/isdn/isdn_bsdcomp.c
--- v2.3.3/linux/drivers/isdn/isdn_bsdcomp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/isdn_bsdcomp.c	Sun May 23 10:03:42 1999
@@ -0,0 +1,934 @@
+/*
+ * BSD compression module
+ *
+ * Patched version for ISDN syncPPP written 1997/1998 by Michael Hipp
+ * The whole module is now SKB based.
+ *
+ * Compile with:
+ *  gcc -O2 -I/usr/src/linux/include -D__KERNEL__ -DMODULE -c isdn_bsdcomp.c
+ */
+
+/*
+ * Original copyright notice:
+ *
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef MODULE
+#error This file must be compiled as a module.
+#endif
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/sched.h>	/* to get the struct task_struct */
+#include <linux/string.h>	/* used in new tty drivers */
+#include <linux/signal.h>	/* used in new tty drivers */
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/segment.h>
+#include <asm/byteorder.h>
+#include <asm/types.h>
+
+#include <linux/if.h>
+
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/ioctl.h>
+
+#include <linux/ppp_defs.h>
+
+#include <linux/isdn.h>
+#include <linux/isdn_ppp.h>
+/* #include <linux/netprotocol.h> */
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/if_arp.h>
+#include <linux/ppp-comp.h>
+
+#include "isdn_ppp.h"
+
+#define BSD_VERSION(x)	((x) >> 5)
+#define BSD_NBITS(x)	((x) & 0x1F)
+
+#define BSD_CURRENT_VERSION	1
+
+#define DEBUG 1
+
+/*
+ * A dictionary for doing BSD compress.
+ */
+
+struct bsd_dict {
+	u32 fcode;
+	u16 codem1;		/* output of hash table -1 */
+	u16 cptr;		/* map code to hash table entry */
+};
+
+struct bsd_db {
+	int            totlen;		/* length of this structure */
+	unsigned int   hsize;		/* size of the hash table */
+	unsigned char  hshift;		/* used in hash function */
+	unsigned char  n_bits;		/* current bits/code */
+	unsigned char  maxbits;		/* maximum bits/code */
+	unsigned char  debug;		/* non-zero if debug desired */
+	unsigned char  unit;		/* ppp unit number */
+	u16 seqno;          		/* sequence # of next packet */
+	unsigned int   mru;		/* size of receive (decompress) bufr */
+	unsigned int   maxmaxcode;	/* largest valid code */
+	unsigned int   max_ent;		/* largest code in use */
+	unsigned int   in_count;	/* uncompressed bytes, aged */
+	unsigned int   bytes_out;	/* compressed bytes, aged */
+	unsigned int   ratio;		/* recent compression ratio */
+	unsigned int   checkpoint;	/* when to next check the ratio */
+	unsigned int   clear_count;	/* times dictionary cleared */
+	unsigned int   incomp_count;	/* incompressible packets */
+	unsigned int   incomp_bytes;	/* incompressible bytes */
+	unsigned int   uncomp_count;	/* uncompressed packets */
+	unsigned int   uncomp_bytes;	/* uncompressed bytes */
+	unsigned int   comp_count;	/* compressed packets */
+	unsigned int   comp_bytes;	/* compressed bytes */
+	unsigned short  *lens;		/* array of lengths of codes */
+	struct bsd_dict *dict;		/* dictionary */
+	int xmit;
+};
+
+#define BSD_OVHD	2		/* BSD compress overhead/packet */
+#define MIN_BSD_BITS	9
+#define BSD_INIT_BITS	MIN_BSD_BITS
+#define MAX_BSD_BITS	15
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define CLEAR	256			/* table clear output code */
+#define FIRST	257			/* first free entry */
+#define LAST	255
+
+#define MAXCODE(b)	((1 << (b)) - 1)
+#define BADCODEM1	MAXCODE(MAX_BSD_BITS);
+
+#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
+					 ^ (unsigned long)(prefix))
+#define BSD_KEY(prefix,suffix)		((((unsigned long)(suffix)) << 16) \
+					 + (unsigned long)(prefix))
+
+#define CHECK_GAP	10000		/* Ratio check interval */
+
+#define RATIO_SCALE_LOG	8
+#define RATIO_SCALE	(1<<RATIO_SCALE_LOG)
+#define RATIO_MAX	(0x7fffffff>>RATIO_SCALE_LOG)
+
+/*
+ * clear the dictionary
+ */
+
+static void bsd_clear(struct bsd_db *db)
+{
+	db->clear_count++;
+	db->max_ent      = FIRST-1;
+	db->n_bits       = BSD_INIT_BITS;
+	db->bytes_out    = 0;
+	db->in_count     = 0;
+	db->incomp_count = 0;
+	db->ratio	     = 0;
+	db->checkpoint   = CHECK_GAP;
+}
+
+/*
+ * If the dictionary is full, then see if it is time to reset it.
+ *
+ * Compute the compression ratio using fixed-point arithmetic
+ * with 8 fractional bits.
+ *
+ * Since we have an infinite stream instead of a single file,
+ * watch only the local compression ratio.
+ *
+ * Since both peers must reset the dictionary at the same time even in
+ * the absence of CLEAR codes (while packets are incompressible), they
+ * must compute the same ratio.
+ */
+static int bsd_check (struct bsd_db *db)	/* 1=output CLEAR */
+{
+    unsigned int new_ratio;
+
+    if (db->in_count >= db->checkpoint)
+      {
+	/* age the ratio by limiting the size of the counts */
+	if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
+	  {
+	    db->in_count  -= (db->in_count  >> 2);
+	    db->bytes_out -= (db->bytes_out >> 2);
+	  }
+	
+	db->checkpoint = db->in_count + CHECK_GAP;
+	
+	if (db->max_ent >= db->maxmaxcode)
+	  {
+	    /* Reset the dictionary only if the ratio is worse,
+	     * or if it looks as if it has been poisoned
+	     * by incompressible data.
+	     *
+	     * This does not overflow, because
+	     *	db->in_count <= RATIO_MAX.
+	     */
+
+	    new_ratio = db->in_count << RATIO_SCALE_LOG;
+	    if (db->bytes_out != 0)
+	      {
+		new_ratio /= db->bytes_out;
+	      }
+	    
+	    if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
+	      {
+		bsd_clear (db);
+		return 1;
+	      }
+	    db->ratio = new_ratio;
+	  }
+      }
+    return 0;
+}
+
+/*
+ * Return statistics.
+ */
+
+static void bsd_stats (void *state, struct compstat *stats)
+{
+	struct bsd_db *db = (struct bsd_db *) state;
+    
+	stats->unc_bytes    = db->uncomp_bytes;
+	stats->unc_packets  = db->uncomp_count;
+	stats->comp_bytes   = db->comp_bytes;
+	stats->comp_packets = db->comp_count;
+	stats->inc_bytes    = db->incomp_bytes;
+	stats->inc_packets  = db->incomp_count;
+	stats->in_count     = db->in_count;
+	stats->bytes_out    = db->bytes_out;
+}
+
+/*
+ * Reset state, as on a CCP ResetReq.
+ */
+static void bsd_reset (void *state,unsigned char code, unsigned char id,
+			unsigned char *data, unsigned len,
+			struct isdn_ppp_resetparams *rsparm)
+{
+	struct bsd_db *db = (struct bsd_db *) state;
+
+	bsd_clear(db);
+	db->seqno       = 0;
+	db->clear_count = 0;
+}
+
+/*
+ * Release the compression structure
+ */
+static void bsd_free (void *state)
+{
+	struct bsd_db *db = (struct bsd_db *) state;
+
+	if (db) {
+		/*
+		 * Release the dictionary
+		 */
+		if (db->dict) {
+			vfree (db->dict);
+			db->dict = NULL;
+		}
+
+		/*
+		 * Release the string buffer
+		 */
+		if (db->lens) {
+			vfree (db->lens);
+			db->lens = NULL;
+		}
+
+		/*
+		 * Finally release the structure itself.
+		 */
+		kfree (db);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+
+/*
+ * Allocate space for a (de) compressor.
+ */
+static void *bsd_alloc (struct isdn_ppp_comp_data *data)
+{
+	int bits;
+	unsigned int hsize, hshift, maxmaxcode;
+	struct bsd_db *db;
+	int decomp;
+
+	static unsigned int htab[][2] = {
+		{ 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , 
+		{ 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 } 
+	};
+		
+	if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
+		|| BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
+		return NULL;
+
+	bits = BSD_NBITS(data->options[0]);
+
+	if(bits < 9 || bits > 15)
+		return NULL;
+
+	hsize = htab[bits-9][0];
+	hshift = htab[bits-9][1];
+	
+	/*
+	 * Allocate the main control structure for this instance.
+	 */
+	maxmaxcode = MAXCODE(bits);
+	db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL);
+	if (!db)
+		return NULL;
+
+	memset (db, 0, sizeof(struct bsd_db));
+
+	db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
+	decomp = db->xmit ? 0 : 1;
+
+	/*
+	 * Allocate space for the dictionary. This may be more than one page in
+	 * length.
+	 */
+	db->dict = (struct bsd_dict *) vmalloc (hsize * sizeof (struct bsd_dict));
+	if (!db->dict) {
+		bsd_free (db);
+		return NULL;
+	}
+
+	MOD_INC_USE_COUNT;
+
+	/*
+	 * If this is the compression buffer then there is no length data.
+	 * For decompression, the length information is needed as well.
+	 */
+	if (!decomp)
+		db->lens = NULL;
+	else {
+		db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
+			sizeof (db->lens[0]));
+		if (!db->lens) {
+			bsd_free (db); /* calls MOD_DEC_USE_COUNT; */
+			return (NULL);
+		}
+	}
+
+	/*
+	 * Initialize the data information for the compression code
+	 */
+	db->totlen     = sizeof (struct bsd_db) + (sizeof (struct bsd_dict) * hsize);
+	db->hsize      = hsize;
+	db->hshift     = hshift;
+	db->maxmaxcode = maxmaxcode;
+	db->maxbits    = bits;
+
+	return (void *) db;
+}
+
+/*
+ * Initialize the database.
+ */
+static int bsd_init (void *state, struct isdn_ppp_comp_data *data, int unit, int debug)
+{
+	struct bsd_db *db = state;
+	int indx;
+	int decomp;
+
+	if(!state || !data) {
+		printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n",unit,(long)state,(long)data);
+		return 0;
+	}
+
+	decomp = db->xmit ? 0 : 1;
+    
+	if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
+		|| (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
+		|| (BSD_NBITS(data->options[0]) != db->maxbits)
+		|| (decomp && db->lens == NULL)) {
+		printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n",data->optlen,data->num,data->options[0],decomp,(unsigned long)db->lens);
+		return 0;
+	}
+
+	if (decomp)
+		for(indx=LAST;indx>=0;indx--)
+			db->lens[indx] = 1;
+
+	indx = db->hsize;
+	while (indx-- != 0) {
+		db->dict[indx].codem1 = BADCODEM1;
+		db->dict[indx].cptr   = 0;
+	}
+
+	db->unit = unit;
+	db->mru  = 0;
+
+	db->debug = 1;
+    
+	bsd_reset(db,0,0,NULL,0,NULL);
+    
+	return 1;
+}
+
+/*
+ * Obtain pointers to the various structures in the compression tables
+ */
+
+#define dict_ptrx(p,idx) &(p->dict[idx])
+#define lens_ptrx(p,idx) &(p->lens[idx])
+
+#ifdef DEBUG
+static unsigned short *lens_ptr(struct bsd_db *db, int idx)
+{
+	if ((unsigned int) idx > (unsigned int) db->maxmaxcode) {
+		printk (KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx);
+		idx = 0;
+	}
+	return lens_ptrx (db, idx);
+}
+
+static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
+{
+	if ((unsigned int) idx >= (unsigned int) db->hsize) {
+		printk (KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx);
+		idx = 0;
+	}
+	return dict_ptrx (db, idx);
+}
+
+#else
+#define lens_ptr(db,idx) lens_ptrx(db,idx)
+#define dict_ptr(db,idx) dict_ptrx(db,idx)
+#endif
+
+/*
+ * compress a packet
+ */
+static int bsd_compress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,int proto)
+{
+	struct bsd_db *db;
+	int hshift;
+	unsigned int max_ent;
+	unsigned int n_bits;
+	unsigned int bitno;
+	unsigned long accm;
+	int ent;
+	unsigned long fcode;
+	struct bsd_dict *dictp;
+	unsigned char c;
+	int hval,disp,ilen,mxcode;
+	unsigned char *rptr = skb_in->data;
+	int isize = skb_in->len;
+
+#define OUTPUT(ent)			\
+  {					\
+    bitno -= n_bits;			\
+    accm |= ((ent) << bitno);		\
+    do	{				\
+        if(skb_out && skb_tailroom(skb_out) > 0) 	\
+      		*(skb_put(skb_out,1)) = (unsigned char) (accm>>24); \
+	accm <<= 8;			\
+	bitno += 8;			\
+    } while (bitno <= 24);		\
+  }
+
+	/*
+	 * If the protocol is not in the range we're interested in,
+	 * just return without compressing the packet.  If it is,
+	 * the protocol becomes the first byte to compress.
+	 */
+	printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
+	
+	ent = proto;
+	if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) )
+		return 0;
+
+	db      = (struct bsd_db *) state;
+	hshift  = db->hshift;
+	max_ent = db->max_ent;
+	n_bits  = db->n_bits;
+	bitno   = 32;
+	accm    = 0;
+	mxcode  = MAXCODE (n_bits);
+	
+	/* This is the PPP header information */
+	if(skb_out && skb_tailroom(skb_out) >= 2) {
+		char *v = skb_put(skb_out,2);
+		/* we only push our own data on the header,
+		  AC,PC and protos is pushed by caller  */
+		v[0] = db->seqno >> 8;
+		v[1] = db->seqno;
+	}
+
+	ilen   = ++isize; /* This is off by one, but that is what is in draft! */
+
+	while (--ilen > 0) {
+		c     = *rptr++;
+		fcode = BSD_KEY  (ent, c);
+		hval  = BSD_HASH (ent, c, hshift);
+		dictp = dict_ptr (db, hval);
+	
+		/* Validate and then check the entry. */
+		if (dictp->codem1 >= max_ent)
+			goto nomatch;
+
+		if (dictp->fcode == fcode) {
+			ent = dictp->codem1 + 1;
+			continue;	/* found (prefix,suffix) */
+		}
+	
+		/* continue probing until a match or invalid entry */
+		disp = (hval == 0) ? 1 : hval;
+
+		do {
+			hval += disp;
+			if (hval >= db->hsize)
+				hval -= db->hsize;
+			dictp = dict_ptr (db, hval);
+			if (dictp->codem1 >= max_ent)
+				goto nomatch;
+		} while (dictp->fcode != fcode);
+
+		ent = dictp->codem1 + 1;	/* finally found (prefix,suffix) */
+		continue;
+	
+nomatch:
+		OUTPUT(ent);		/* output the prefix */
+	
+		/* code -> hashtable */
+		if (max_ent < db->maxmaxcode) {
+			struct bsd_dict *dictp2;
+			struct bsd_dict *dictp3;
+			int indx;
+
+			/* expand code size if needed */
+			if (max_ent >= mxcode) {
+				db->n_bits = ++n_bits;
+				mxcode = MAXCODE (n_bits);
+			}
+	    
+			/* 
+			 * Invalidate old hash table entry using
+			 * this code, and then take it over.
+			 */
+			dictp2 = dict_ptr (db, max_ent + 1);
+			indx   = dictp2->cptr;
+			dictp3 = dict_ptr (db, indx);
+
+			if (dictp3->codem1 == max_ent)
+				dictp3->codem1 = BADCODEM1;
+
+			dictp2->cptr   = hval;
+			dictp->codem1  = max_ent;
+			dictp->fcode = fcode;
+			db->max_ent    = ++max_ent;
+
+			if (db->lens) {
+				unsigned short *len1 = lens_ptr (db, max_ent);
+				unsigned short *len2 = lens_ptr (db, ent);
+				*len1 = *len2 + 1;
+			}
+		}
+		ent = c;
+	}
+    
+	OUTPUT(ent);		/* output the last code */
+
+	if(skb_out)
+		db->bytes_out    += skb_out->len; /* Do not count bytes from here */
+	db->uncomp_bytes += isize;
+	db->in_count     += isize;
+	++db->uncomp_count;
+	++db->seqno;
+
+	if (bitno < 32)
+		++db->bytes_out; /* must be set before calling bsd_check */
+
+	/*
+	 * Generate the clear command if needed
+	 */
+
+	if (bsd_check(db))
+		OUTPUT (CLEAR);
+
+	/*
+	 * Pad dribble bits of last code with ones.
+	 * Do not emit a completely useless byte of ones.
+	 */
+	if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0) 
+		*(skb_put(skb_out,1)) = (unsigned char) ((accm | (0xff << (bitno-8))) >> 24);
+    
+	/*
+	 * Increase code size if we would have without the packet
+	 * boundary because the decompressor will do so.
+	 */
+	if (max_ent >= mxcode && max_ent < db->maxmaxcode)
+		db->n_bits++;
+
+	/* If output length is too large then this is an incompressible frame. */
+	if (!skb_out || (skb_out && skb_out->len >= skb_in->len) ) {
+		++db->incomp_count;
+		db->incomp_bytes += isize;
+		return 0;
+	}
+
+	/* Count the number of compressed frames */
+	++db->comp_count;
+	db->comp_bytes += skb_out->len;
+	return skb_out->len;
+
+#undef OUTPUT
+}
+
+/*
+ * Update the "BSD Compress" dictionary on the receiver for
+ * incompressible data by pretending to compress the incoming data.
+ */
+static void bsd_incomp (void *state, struct sk_buff *skb_in,int proto)
+{
+	bsd_compress (state, skb_in, NULL, proto);
+}
+
+/*
+ * Decompress "BSD Compress".
+ */
+static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,
+			   struct isdn_ppp_resetparams *rsparm)
+{
+	struct bsd_db *db;
+	unsigned int max_ent;
+	unsigned long accm;
+	unsigned int bitno;		/* 1st valid bit in accm */
+	unsigned int n_bits;
+	unsigned int tgtbitno;	/* bitno when we have a code */
+	struct bsd_dict *dictp;
+	int seq;
+	unsigned int incode;
+	unsigned int oldcode;
+	unsigned int finchar;
+	unsigned char *p,*ibuf;
+	int ilen;
+	int codelen;
+	int extra;
+
+	db       = (struct bsd_db *) state;
+	max_ent  = db->max_ent;
+	accm     = 0;
+	bitno    = 32;		/* 1st valid bit in accm */
+	n_bits   = db->n_bits;
+	tgtbitno = 32 - n_bits;	/* bitno when we have a code */
+
+	printk(KERN_DEBUG "bsd_decompress called\n");
+
+	if(!skb_in || !skb_out) {
+		printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
+		return DECOMP_ERROR;
+	}
+    
+	/*
+	 * Get the sequence number.
+	 */
+	if( (p = skb_pull(skb_in,2)) == NULL) {
+		return DECOMP_ERROR;
+	}
+	p-=2;
+	seq   = (p[0] << 8) + p[1];
+	ilen  = skb_in->len;
+	ibuf = skb_in->data;
+
+	/*
+	 * Check the sequence number and give up if it differs from
+	 * the value we're expecting.
+	 */
+	if (seq != db->seqno) {
+		if (db->debug) {
+			printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n",
+				db->unit, seq, db->seqno - 1);
+		}
+		return DECOMP_ERROR;
+	}
+
+	++db->seqno;
+	db->bytes_out += ilen;
+
+	if(skb_tailroom(skb_out) > 0)
+		*(skb_put(skb_out,1)) = 0;
+	else
+		return DECOMP_ERR_NOMEM;
+    
+	oldcode = CLEAR;
+
+	/*
+	 * Keep the checkpoint correctly so that incompressible packets
+	 * clear the dictionary at the proper times.
+	 */
+
+	for (;;) {
+		if (ilen-- <= 0) {
+			db->in_count += (skb_out->len - 1); /* don't count the header */
+			break;
+		}
+
+		/*
+		 * Accumulate bytes until we have a complete code.
+		 * Then get the next code, relying on the 32-bit,
+		 * unsigned accm to mask the result.
+		 */
+
+		bitno -= 8;
+		accm  |= *ibuf++ << bitno;
+		if (tgtbitno < bitno)
+			continue;
+
+		incode = accm >> tgtbitno;
+		accm <<= n_bits;
+		bitno += n_bits;
+
+		/*
+		 * The dictionary must only be cleared at the end of a packet.
+		 */
+	
+		if (incode == CLEAR) {
+			if (ilen > 0) {
+				if (db->debug)
+					printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit);
+				return DECOMP_FATALERROR;	/* probably a bug */
+			}
+			bsd_clear(db);
+			break;
+		}
+
+		if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
+			|| (incode > max_ent && oldcode == CLEAR)) {
+			if (db->debug) {
+				printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
+					db->unit, incode, oldcode);
+				printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n",
+					max_ent, skb_out->len, db->seqno);
+			}
+			return DECOMP_FATALERROR;	/* probably a bug */
+		}
+	
+		/* Special case for KwKwK string. */
+		if (incode > max_ent) {
+			finchar = oldcode;
+			extra   = 1;
+		} else {
+			finchar = incode;
+			extra   = 0;
+		}
+
+		codelen = *(lens_ptr (db, finchar));
+		if( skb_tailroom(skb_out) < codelen + extra) {
+			if (db->debug) {
+				printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit);
+#ifdef DEBUG
+				printk(KERN_DEBUG "  len=%d, finchar=0x%x, codelen=%d,skblen=%d\n",
+					ilen, finchar, codelen, skb_out->len);
+#endif
+			}
+			return DECOMP_FATALERROR;
+		}
+
+		/*
+		 * Decode this code and install it in the decompressed buffer.
+		 */
+
+		p     = skb_put(skb_out,codelen);
+		p += codelen;
+		while (finchar > LAST) {
+			struct bsd_dict *dictp2 = dict_ptr (db, finchar);
+	    
+			dictp = dict_ptr (db, dictp2->cptr);
+
+#ifdef DEBUG
+			if (--codelen <= 0 || dictp->codem1 != finchar-1) {
+				if (codelen <= 0) {
+					printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit);
+					printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent);
+				} else {
+					if (dictp->codem1 != finchar-1) {
+						printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",db->unit, incode, finchar);
+						printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1);
+					}
+				}
+				return DECOMP_FATALERROR;
+			}
+#endif
+
+			{
+				u32 fcode = dictp->fcode;
+				*--p    = (fcode >> 16) & 0xff;
+				finchar = fcode & 0xffff;
+			}
+		}
+		*--p = finchar;
+	
+#ifdef DEBUG
+		if (--codelen != 0)
+			printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent);
+#endif
+	
+		if (extra)		/* the KwKwK case again */
+			*(skb_put(skb_out,1)) = finchar;
+	
+		/*
+		 * If not first code in a packet, and
+		 * if not out of code space, then allocate a new code.
+		 *
+		 * Keep the hash table correct so it can be used
+		 * with uncompressed packets.
+		 */
+		if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
+			struct bsd_dict *dictp2, *dictp3;
+			u16  *lens1,  *lens2;
+			unsigned long fcode;
+			int hval, disp, indx;
+	    
+			fcode = BSD_KEY(oldcode,finchar);
+			hval  = BSD_HASH(oldcode,finchar,db->hshift);
+			dictp = dict_ptr (db, hval);
+	    
+			/* look for a free hash table entry */
+			if (dictp->codem1 < max_ent) {
+				disp = (hval == 0) ? 1 : hval;
+				do {
+					hval += disp;
+					if (hval >= db->hsize)
+						hval -= db->hsize;
+					dictp = dict_ptr (db, hval);
+				} while (dictp->codem1 < max_ent);
+			}
+	    
+			/*
+			 * Invalidate previous hash table entry
+			 * assigned this code, and then take it over
+			 */
+
+			dictp2 = dict_ptr (db, max_ent + 1);
+			indx   = dictp2->cptr;
+			dictp3 = dict_ptr (db, indx);
+
+			if (dictp3->codem1 == max_ent)
+				dictp3->codem1 = BADCODEM1;
+
+			dictp2->cptr   = hval;
+			dictp->codem1  = max_ent;
+			dictp->fcode = fcode;
+			db->max_ent    = ++max_ent;
+
+			/* Update the length of this string. */
+			lens1  = lens_ptr (db, max_ent);
+			lens2  = lens_ptr (db, oldcode);
+			*lens1 = *lens2 + 1;
+	    
+			/* Expand code size if needed. */
+			if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
+				db->n_bits = ++n_bits;
+				tgtbitno   = 32-n_bits;
+			}
+		}
+		oldcode = incode;
+	}
+
+	++db->comp_count;
+	++db->uncomp_count;
+	db->comp_bytes   += skb_in->len - BSD_OVHD;
+	db->uncomp_bytes += skb_out->len;
+
+	if (bsd_check(db)) {
+		if (db->debug)
+			printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
+				db->unit, db->seqno - 1);
+	}
+	return skb_out->len;
+}
+
+/*************************************************************
+ * Table of addresses for the BSD compression module
+ *************************************************************/
+
+static struct isdn_ppp_compressor ippp_bsd_compress = {
+	NULL,NULL,		/* prev,next: overwritten by isdn_ppp */
+	CI_BSD_COMPRESS,	/* compress_proto */
+	bsd_alloc,		/* alloc */
+	bsd_free,		/* free */
+	bsd_init,		/* init */
+	bsd_reset,		/* reset */
+	bsd_compress,		/* compress */
+	bsd_decompress,		/* decompress */
+	bsd_incomp,		/* incomp */
+	bsd_stats		/* comp_stat */
+};
+
+/*************************************************************
+ * Module support routines
+ *************************************************************/
+
+int init_module(void)
+{
+	int answer = isdn_ppp_register_compressor (&ippp_bsd_compress);
+	if (answer == 0)
+		printk (KERN_INFO "PPP BSD Compression module registered\n");
+	return answer;
+}
+
+void cleanup_module(void)
+{
+	isdn_ppp_unregister_compressor (&ippp_bsd_compress);
+}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_budget.c linux/drivers/isdn/isdn_budget.c
--- v2.3.3/linux/drivers/isdn/isdn_budget.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/isdn_budget.c	Sun May 23 10:03:42 1999
@@ -0,0 +1,206 @@
+/* $Id: isdn_budget.c,v 1.3 1998/10/23 10:18:39 paul Exp $
+ *
+ * Linux ISDN subsystem, budget-accounting for network interfaces.
+ *
+ * Copyright 1997       by Christian Lademann <c...@zls.de>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_budget.c,v $
+ * Revision 1.3  1998/10/23 10:18:39  paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.2  1998/03/07 23:17:30  fritz
+ * Added RCS keywords
+ * Bugfix: Did not compile without isdn_dumppkt beeing enabled.
+ *
+ */
+
+/*
+30.06.97:cal:angelegt
+04.11.97:cal:budget.period: int --> time_t
+*/
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/isdn.h>
+#include "isdn_common.h"
+#include "isdn_net.h"
+
+#ifdef CONFIG_ISDN_BUDGET
+
+#define	VERBOSE_PRINTK(v, l, p...)	{ \
+	if(dev->net_verbose >= (v)) { \
+		printk(l ## p); \
+	} else { ; } \
+}
+
+
+int
+isdn_net_budget(int type, struct device *ndev) {
+	isdn_net_local		*lp = (isdn_net_local *)ndev->priv;
+	int			i, ret = 0;
+
+	switch(type) {
+	case ISDN_BUDGET_INIT:
+		for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
+			lp->budget [i] .amount = -1;
+			lp->budget [i] .used = 0;
+			lp->budget [i] .period = (time_t)0;
+			lp->budget [i] .period_started = (time_t)0;
+			lp->budget [i] .last_check = CURRENT_TIME;
+			lp->budget [i] .notified = 0;
+		}
+
+		return(0);
+		break;
+
+	case ISDN_BUDGET_CHECK_DIAL:
+	case ISDN_BUDGET_CHECK_CHARGE:
+	case ISDN_BUDGET_CHECK_ONLINE:
+		ret = 0;
+
+		for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
+			if(lp->budget [i] .amount < 0)
+				continue;
+
+			if(lp->budget [i] .period_started + lp->budget [i] .period < CURRENT_TIME) {
+				lp->budget [i] .used = 0;
+				lp->budget [i] .period_started = CURRENT_TIME;
+				lp->budget [i] .notified = 0;
+			}
+
+			if(lp->budget [i] .used >= lp->budget [i] .amount)
+				ret |= (1 << i);
+		}
+
+		switch(type) {
+		case ISDN_BUDGET_CHECK_DIAL:
+			if(! ret) {
+				lp->budget [ISDN_BUDGET_DIAL] .used++;
+				lp->budget [ISDN_BUDGET_DIAL] .last_check = CURRENT_TIME;
+			}
+			break;
+
+		case ISDN_BUDGET_CHECK_CHARGE:
+			lp->budget [ISDN_BUDGET_CHARGE] .used++;
+			lp->budget [ISDN_BUDGET_CHARGE] .last_check = CURRENT_TIME;
+			break;
+
+		case ISDN_BUDGET_CHECK_ONLINE:
+			if(lp->budget [ISDN_BUDGET_ONLINE] .last_check) {
+				lp->budget [ISDN_BUDGET_ONLINE] .used += (CURRENT_TIME - lp->budget [ISDN_BUDGET_ONLINE] .last_check);
+			}
+
+			lp->budget [ISDN_BUDGET_ONLINE] .last_check = CURRENT_TIME;
+			break;
+		}
+
+/*
+		if(ret)
+			lp->flags |= ISDN_NET_DM_OFF;
+*/
+		for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
+			if(ret & (1 << i) && ! lp->budget [i] .notified) {
+				switch(i) {
+				case ISDN_BUDGET_DIAL:
+					printk(KERN_WARNING "isdn_budget: dial budget used up.\n");
+					break;
+
+				case ISDN_BUDGET_CHARGE:
+					printk(KERN_WARNING "isdn_budget: charge budget used up.\n");
+					break;
+
+				case ISDN_BUDGET_ONLINE:
+					printk(KERN_WARNING "isdn_budget: online budget used up.\n");
+					break;
+
+				default:
+					printk(KERN_WARNING "isdn_budget: budget #%d used up.\n", i);
+					break;
+				}
+
+				lp->budget [i] .notified = 1;
+			}
+		}
+
+		return(ret);
+		break;
+
+	case ISDN_BUDGET_START_ONLINE:
+		lp->budget [ISDN_BUDGET_ONLINE] .last_check = CURRENT_TIME;
+		return(0);
+
+		break;
+	}
+
+	return(-1);
+}
+
+
+int
+isdn_budget_ioctl(isdn_ioctl_budget *iocmd) {
+	isdn_net_dev		*p = isdn_net_findif(iocmd->name);
+
+	if(p) {
+		switch(iocmd->command) {
+		case ISDN_BUDGET_SET_BUDGET:
+			if(! suser())
+				return(-EPERM);
+
+			if(iocmd->budget < 0 || iocmd->budget > ISDN_BUDGET_NUM_BUDGET)
+				return(-EINVAL);
+
+			if(iocmd->amount < 0)
+				iocmd->amount = -1;
+
+			p->local->budget [iocmd->budget] .amount = iocmd->amount;
+			p->local->budget [iocmd->budget] .period = iocmd->period;
+
+			if(iocmd->used <= 0)
+				p->local->budget [iocmd->budget] .used = 0;
+			else
+				p->local->budget [iocmd->budget] .used = iocmd->used;
+
+			if(iocmd->period_started == (time_t)0)
+				p->local->budget [iocmd->budget] .period_started = CURRENT_TIME;
+			else
+				p->local->budget [iocmd->budget] .period_started = iocmd->period_started;
+
+			return(0);
+			break;
+
+		case ISDN_BUDGET_GET_BUDGET:
+			if(iocmd->budget < 0 || iocmd->budget > ISDN_BUDGET_NUM_BUDGET)
+				return(-EINVAL);
+
+			iocmd->amount = p->local->budget [iocmd->budget] .amount;
+			iocmd->used = p->local->budget [iocmd->budget] .used;
+			iocmd->period = p->local->budget [iocmd->budget] .period;
+			iocmd->period_started = p->local->budget [iocmd->budget] .period_started;
+
+			return(0);
+			break;
+
+		default:
+			return(-EINVAL);
+			break;
+		}
+	}
+	return(-ENODEV);
+}
+#endif
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c
--- v2.3.3/linux/drivers/isdn/isdn_cards.c	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_cards.c	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_cards.c,v 1.7 1998/02/20 17:24:28 fritz Exp $
+/* $Id: isdn_cards.c,v 1.9 1999/04/12 12:33:11 fritz Exp $
X 
X  * Linux ISDN subsystem, initialization for non-modularized drivers.
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994,95,96 by Fritz Elfert (fr...@isdn4linux.de)
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
@@ -19,6 +19,12 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_cards.c,v $
+ * Revision 1.9  1999/04/12 12:33:11  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.8  1999/03/29 11:13:23  armin
+ * Added eicon driver init.
+ *
X  * Revision 1.7  1998/02/20 17:24:28  fritz
X  * Added ACT2000 init.
X  *
@@ -56,6 +62,10 @@
X extern void pcbit_init(void);
X #endif
X 
+#ifdef CONFIG_ISDN_DRV_EICON
+extern void eicon_init(void);
+#endif
+
X #ifdef CONFIG_ISDN_DRV_AVMB1
X extern void avmb1_init(void);
X extern void capi_init(void);
@@ -87,5 +97,8 @@
X #endif
X #if CONFIG_ISDN_DRV_ACT2000
X 	act2000_init();
+#endif
+#if CONFIG_ISDN_DRV_EICON
+	eicon_init();
X #endif
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_cards.h linux/drivers/isdn/isdn_cards.h
--- v2.3.3/linux/drivers/isdn/isdn_cards.h	Thu Feb 27 10:57:29 1997
+++ linux/drivers/isdn/isdn_cards.h	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_cards.h,v 1.2 1997/02/03 23:31:55 fritz Exp $
+/* $Id: isdn_cards.h,v 1.3 1999/04/12 12:33:13 fritz Exp $
X 
X  * Linux ISDN subsystem, initialization for non-modularized drivers.
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fr...@isdn4linux.de)
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
@@ -19,6 +19,9 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_cards.h,v $
+ * Revision 1.3  1999/04/12 12:33:13  fritz
+ * Changes from 2.0 tree.
+ *
X  * Revision 1.2  1997/02/03 23:31:55  fritz
X  * Reformatted according CodingStyle
X  *
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.3.3/linux/drivers/isdn/isdn_common.c	Fri May 14 18:55:18 1999
+++ linux/drivers/isdn/isdn_common.c	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.c,v 1.55 1998/02/23 23:35:32 fritz Exp $
+/* $Id: isdn_common.c,v 1.75 1999/04/18 14:06:47 fritz Exp $
X 
X  * Linux ISDN subsystem, common used functions (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fr...@isdn4linux.de)
X  * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
X  * Copyright 1995,96    by Michael Hipp (Michae...@student.uni-tuebingen.de)
X  *
@@ -20,11 +20,85 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
X  * $Log: isdn_common.c,v $
+ * Revision 1.75  1999/04/18 14:06:47  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.74  1999/04/12 13:16:45  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.73 1999/04/12 12:33:15 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.72  1999/03/02 12:04:44  armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.71  1999/01/28 09:10:43  armin
+ * Fixed bad while-loop in isdn_readbch().
+ *
+ * Revision 1.70  1999/01/15 19:58:54  he
+ * removed compatibiltity macro
+ *
+ * Revision 1.69  1998/09/07 21:59:58  he
+ * flush method for 2.1.118 and above
+ * updated IIOCTLNETGPN
+ *
+ * Revision 1.68  1998/08/31 21:09:45  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
+ * Revision 1.67  1998/06/26 15:12:21  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.66  1998/06/17 19:50:41  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.65  1998/06/07 00:20:00  fritz
+ * abc cleanup.
+ *
+ * Revision 1.64  1998/06/02 12:10:03  detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.63  1998/05/03 17:40:38  detabc
+ * Include abc-extension-support for >= 2.1.x Kernels in
+ * isdn_net.c and isdn_common.c. alpha-test OK and running !
+ *
+ * Revision 1.62  1998/04/14 16:28:43  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.61  1998/03/22 18:50:46  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.60  1998/03/19 13:18:18  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 1.59  1998/03/09 17:46:23  he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.58  1998/03/07 22:35:24  fritz
+ * Starting generic module support (Nothing usable yet).
+ *
+ * Revision 1.57  1998/03/07 18:21:01  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.56  1998/02/25 17:49:38  he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
X  * Revision 1.55  1998/02/23 23:35:32  fritz
X  * Eliminated some compiler warnings.
X  *
@@ -269,7 +343,7 @@
X 
X isdn_dev *dev = (isdn_dev *) 0;
X 
-static char *isdn_revision = "$Revision: 1.55 $";
+static char *isdn_revision = "$Revision: 1.75 $";
X 
X extern char *isdn_net_revision;
X extern char *isdn_tty_revision;
@@ -290,13 +364,36 @@
X void
X isdn_MOD_INC_USE_COUNT(void)
X {
+	int i;
+
X 	MOD_INC_USE_COUNT;
+	for (i = 0; i < dev->drivers; i++) {
+		isdn_ctrl cmd;
+
+		cmd.driver = i;
+		cmd.arg = 0;
+		cmd.command = ISDN_CMD_LOCK;
+		isdn_command(&cmd);
+		dev->drv[i]->locks++;
+	}
X }
X 
X void
X isdn_MOD_DEC_USE_COUNT(void)
X {
+	int i;
+
X 	MOD_DEC_USE_COUNT;
+	for (i = 0; i < dev->drivers; i++)
+		if (dev->drv[i]->locks > 0) {
+			isdn_ctrl cmd;
+
+			cmd.driver = i;
+			cmd.arg = 0;
+			cmd.command = ISDN_CMD_UNLOCK;
+			isdn_command(&cmd);
+			dev->drv[i]->locks--;
+		}
X }
X 
X #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
@@ -312,6 +409,82 @@
X }
X #endif
X 
+/*
+ * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
+ * It was originally written and put to PD by r...@mirror.TMC.COM (Rich Salz)
+ */
+static int
+isdn_star(char *s, char *p)
+{
+	while (isdn_wildmat(s, p)) {
+		if (*++s == '\0')
+			return (2);
+	}
+	return (0);
+}
+
+/*
+ * Shell-type Pattern-matching for incoming caller-Ids
+ * This function gets a string in s and checks, if it matches the pattern
+ * given in p.
+ *
+ * Return:
+ *   0 = match.
+ *   1 = no match.
+ *   2 = no match. Would eventually match, if s would be longer.
+ *
+ * Possible Patterns:
+ *
+ * '?'     matches one character
+ * '*'     matches zero or more characters
+ * [xyz]   matches the set of characters in brackets.
+ * [^xyz]  matches any single character not in the set of characters
+ */
+
+int
+isdn_wildmat(char *s, char *p)
+{
+	register int last;
+	register int matched;
+	register int reverse;
+	register int nostar = 1;
+
+	for (; *p; s++, p++)
+		switch (*p) {
+			case '\\':
+				/*
+				 * Literal match with following character,
+				 * fall through.
+				 */
+				p++;
+			default:
+				if (*s != *p)
+					return (*s == '\0')?2:1;
+				continue;
+			case '?':
+				/* Match anything. */
+				if (*s == '\0')
+					return (2);
+				continue;
+			case '*':
+				nostar = 0;	
+				/* Trailing star matches everything. */
+				return (*++p ? isdn_star(s, p) : 0);
+			case '[':
+				/* [^....] means inverse character class. */
+				if ((reverse = (p[1] == '^')))
+					p++;
+				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
+					/* This next line requires a good C compiler. */
+					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
+						matched = 1;
+				if (matched == reverse)
+					return (1);
+				continue;
+		}
+	return (*s == '\0')?0:nostar;
+}
+
X static void
X isdn_free_queue(struct sk_buff_head *queue)
X {
@@ -345,7 +518,6 @@
X isdn_timer_funct(ulong dummy)
X {
X 	int tf = dev->tflags;
-
X 	if (tf & ISDN_TIMER_FAST) {
X 		if (tf & ISDN_TIMER_MODEMREAD)
X 			isdn_tty_readmodem();
@@ -374,13 +546,16 @@
X 				if (tf & ISDN_TIMER_KEEPALIVE)
X 					isdn_net_slarp_out();
X 			}
+			if (tf & ISDN_TIMER_CARRIER)
+				isdn_tty_carrier_timeout();
X #if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
X 			if (tf & ISDN_TIMER_IPPP)
X 				isdn_ppp_timer_timeout();
X #endif
X 		}
X 	}
-	if (tf) {
+	if (tf) 
+	{
X 		int flags;
X 
X 		save_flags(flags);
@@ -506,6 +681,29 @@
X 	isdn_command(&cmd);
X }
X 
+/*
+ * Begin of a CAPI like LL<->HL interface, currently used only for 
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include "avmb1/capicmd.h"  /* this should be moved in a common place */
+
+int
+isdn_capi_rec_hl_msg(capi_msg *cm) {
+	
+	int di;
+	int ch;
+	
+	di = (cm->adr.Controller & 0x7f) -1;
+	ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
+	switch(cm->Command) {
+		case CAPI_FACILITY:
+			/* in the moment only handled in tty */
+			return(isdn_tty_capi_facility(cm));
+		default:
+			return(-1);
+	}
+}
+
X static int
X isdn_status_callback(isdn_ctrl * c)
X {
@@ -540,13 +738,13 @@
X 			wake_up_interruptible(&dev->drv[di]->st_waitq);
X 			break;
X 		case ISDN_STAT_RUN:
-			dev->drv[di]->running = 1;
+			dev->drv[di]->flags |= DRV_FLAG_RUNNING;
X 			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
X 				if (dev->drvmap[i] == di)
X 					isdn_all_eaz(di, dev->chanmap[i]);
X 			break;
X 		case ISDN_STAT_STOP:
-			dev->drv[di]->running = 0;
+			dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
X 			break;
X 		case ISDN_STAT_ICALL:
X 			if (i < 0)
@@ -562,19 +760,17 @@
X 				return 0;
X 			}
X 			/* Try to find a network-interface which will accept incoming call */
-			cmd.driver = di;
-			cmd.arg = c->arg;
-			cmd.command = ISDN_CMD_LOCK;
-			isdn_command(&cmd);
X 			r = isdn_net_find_icall(di, c->arg, i, c->parm.setup);
X 			switch (r) {
X 				case 0:
X 					/* No network-device replies.
-					 * Try ttyI's
+					 * Try ttyI's.
+					 * These return 0 on no match, 1 on match and
+					 * 3 on eventually match, if CID is longer.
X 					 */
-					if (isdn_tty_find_icall(di, c->arg, c->parm.setup) >= 0)
-						retval = 1;
-					else if (dev->drv[di]->reject_bus) {
+					retval = isdn_tty_find_icall(di, c->arg, c->parm.setup);
+					if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
+						/* No tty responding */
X 						cmd.driver = di;
X 						cmd.arg = c->arg;
X 						cmd.command = ISDN_CMD_HANGUP;
@@ -606,13 +802,14 @@
X 					/* ... then start callback. */
X 					isdn_net_dial();
X 					break;
+				case 5:
+					/* Number would eventually match, if longer */
+					retval = 3;
+					break;
X 			}
-			if (retval != 1) {
-				cmd.driver = di;
-				cmd.arg = c->arg;
-				cmd.command = ISDN_CMD_UNLOCK;
-				isdn_command(&cmd);
-			}
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
+#endif
X 			return retval;
X 			break;
X 		case ISDN_STAT_CINF:
@@ -664,7 +861,7 @@
X #endif
X 			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
X 				return 0;
-			dev->drv[di]->flags &= ~(1 << (c->arg));
+			dev->drv[di]->online &= ~(1 << (c->arg));
X 			isdn_info_update();
X 			/* Signal hangup to network-devices */
X 			if (isdn_net_stat_callback(i, c))
@@ -682,7 +879,7 @@
X 			/* Signal B-channel-connect to network-devices */
X 			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
X 				return 0;
-			dev->drv[di]->flags |= (1 << (c->arg));
+			dev->drv[di]->online |= (1 << (c->arg));
X 			isdn_info_update();
X 			if (isdn_net_stat_callback(i, c))
X 				break;
@@ -698,7 +895,7 @@
X #endif
X 			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
X 				return 0;
-			dev->drv[di]->flags &= ~(1 << (c->arg));
+			dev->drv[di]->online &= ~(1 << (c->arg));
X 			isdn_info_update();
X #ifdef CONFIG_ISDN_X25
X 			/* Signal hangup to network-devices */
@@ -723,6 +920,9 @@
X 				break;
X 			break;
X 		case ISDN_STAT_ADDCH:
+			if (isdn_add_channels(dev->drv[di], di, c->arg, 1))
+				return -1;
+			isdn_info_update();
X 			break;
X 		case ISDN_STAT_UNLOAD:
X 			save_flags(flags);
@@ -741,6 +941,9 @@
X 				isdn_free_queue(&dev->drv[di]->rpqueue[i]);
X 			kfree(dev->drv[di]->rpqueue);
X 			kfree(dev->drv[di]->rcv_waitq);
+#if LINUX_VERSION_CODE < 131841
+			kfree(dev->drv[di]->snd_waitq);
+#endif
X 			kfree(dev->drv[di]);
X 			dev->drv[di] = NULL;
X 			dev->drvid[di][0] = '\0';
@@ -749,6 +952,8 @@
X 			return 0;
X 		case ISDN_STAT_L1ERR:
X 			break;
+		case CAPI_PUT_MESSAGE:
+			return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
X 		default:
X 			return -1;
X 	}
@@ -784,7 +989,11 @@
X  * of the mapping (di,ch)<->minor, happen during the sleep? --he 
X  */
X int
+#if LINUX_VERSION_CODE < 131841
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
+#else
X isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
+#endif
X {
X 	int left;
X 	int count;
@@ -818,7 +1027,8 @@
X 
X 			dflag = 0;
X 			count_pull = count_put = 0;
-			while ((count_pull < skb->len) && (left-- > 0)) {
+			while ((count_pull < skb->len) && (left > 0)) {
+				left--;
X 				if (dev->drv[di]->DLEflag & DLEmask) {
X 					*cp++ = DLE;
X 					dev->drv[di]->DLEflag &= ~DLEmask;
@@ -893,8 +1103,6 @@
X 	return (dev->chanmap[minor]);
X }
X 
-#define INF_DV 0x01             /* Data version for /dev/isdninfo */
-
X static char *
X isdn_statstr(void)
X {
@@ -930,7 +1138,7 @@
X 	p = istatbuf + strlen(istatbuf);
X 	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
X 		if (dev->drv[i]) {
-			sprintf(p, "%ld ", dev->drv[i]->flags);
+			sprintf(p, "%ld ", dev->drv[i]->online);
X 			p = istatbuf + strlen(istatbuf);
X 		} else {
X 			sprintf(p, "? ");
@@ -996,7 +1204,7 @@
X 		drvidx = isdn_minor2drv(minor);
X 		if (drvidx < 0)
X 			return -ENODEV;
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
X 			return -ENODEV;
X 		chidx = isdn_minor2chan(minor);
X 		if(  ! (p = kmalloc(count,GFP_KERNEL))  ) return -ENOMEM;
@@ -1066,7 +1274,7 @@
X 		drvidx = isdn_minor2drv(minor);
X 		if (drvidx < 0)
X 			return -ENODEV;
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
X 			return -ENODEV;
X 		chidx = isdn_minor2chan(minor);
X 		while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
@@ -1080,7 +1288,7 @@
X 		/*
X 		 * We want to use the isdnctrl device to load the firmware
X 		 *
-		 if (!dev->drv[drvidx]->running)
+		 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
X 		 return -ENODEV;
X 		 */
X 		if (dev->drv[drvidx]->interface->writecmd)
@@ -1131,143 +1339,6 @@
X 	return POLLERR;
X }
X 
-/* 
- * This accesses user space with interrupts off, but is not needed by
- * any of the isdn4k-util programs anyway. Thus, in contrast to your
- * first impression after looking at the code, fixing is trival!*/
-#if 0 
-static int
-isdn_set_allcfg(char *src)
-{
-	int ret;
-	int i;
-	ulong flags;
-	isdn_net_ioctl_cfg cfg;
-	isdn_net_ioctl_phone phone;
-
-	if ((ret = isdn_net_rmall()))
-		return ret;
-	if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT;
-	save_flags(flags);
-	cli();
-	src += sizeof(int);
-	while (i) {
-		int phone_len;
-		int out_flag;
-
-		if (copy_from_user((char *) &cfg, src, sizeof(cfg))) {
-			restore_flags(flags);
-			return -EFAULT;
-		}
-		src += sizeof(cfg);
-		if (!isdn_net_new(cfg.name, NULL)) {
-			restore_flags(flags);
-			return -EIO;
-		}
-		if ((ret = isdn_net_setcfg(&cfg))) {
-			restore_flags(flags);
-			return ret;
-		}
-		phone_len = out_flag = 0;
-		while (out_flag < 2) {
-			if ((ret = verify_area(VERIFY_READ, src, 1))) {
-				restore_flags(flags);
-				return ret;
-			}
-			get_user(phone.phone[phone_len], src++);
-			if ((phone.phone[phone_len] == ' ') ||
-			    (phone.phone[phone_len] == '\0')) {
-				if (phone_len) {
-					phone.phone[phone_len] = '\0';
-					strcpy(phone.name, cfg.name);
-					phone.outgoing = out_flag;
-					if ((ret = isdn_net_addphone(&phone))) {
-						restore_flags(flags);
-						return ret;
-					}
-				} else
-					out_flag++;
-				phone_len = 0;
-			}
-			if (++phone_len >= sizeof(phone.phone))
-				printk(KERN_WARNING
-				       "%s: IIOCSETSET phone number too long, ignored\n",
-				       cfg.name);
-		}
-		i--;
-	}
-	restore_flags(flags);
-	return 0;
-}
-
-static int
-isdn_get_allcfg(char *dest)
-{
-	isdn_net_ioctl_cfg cfg;
-	isdn_net_ioctl_phone phone;
-	isdn_net_dev *p;
-	ulong flags;
-	int ret;
-
-	/* Walk through netdev-chain */
-	save_flags(flags);
-	cli();
-	p = dev->netdev;
-	while (p) {
-		isdn_net_local *lp = p->local;
-
-		if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200))) {
-			restore_flags(flags);
-			return ret;
-		}
-		strcpy(cfg.eaz, lp->msn);
-		cfg.exclusive = lp->exclusive;
-		if (lp->pre_device >= 0) {
-			sprintf(cfg.drvid, "%s,%d", dev->drvid[lp->pre_device],
-				lp->pre_channel);
-		} else
-			cfg.drvid[0] = '\0';
-		cfg.onhtime = lp->onhtime;
-		cfg.charge = lp->charge;
-		cfg.l2_proto = lp->l2_proto;
-		cfg.l3_proto = lp->l3_proto;
-		cfg.p_encap = lp->p_encap;
-		cfg.secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
-		cfg.callback = (lp->flags & ISDN_NET_CALLBACK) ? 1 : 0;
-		cfg.chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
-		cfg.ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
-		cfg.chargeint = lp->chargeint;
-		if (copy_to_user(dest, lp->name, 10)) {
-			restore_flags(flags);
-			return -EFAULT;
-		}
-		dest += 10;
-		if (copy_to_user(dest, (char *) &cfg, sizeof(cfg))) {
-			restore_flags(flags);
-			return -EFAULT;
-		}
-		dest += sizeof(cfg);
-		strcpy(phone.name, lp->name);
-		phone.outgoing = 0;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-			restore_flags(flags);
-			return ret;
-		} else
-			dest += ret;
-		strcpy(phone.name, lp->name);
-		phone.outgoing = 1;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-			restore_flags(flags);
-			return ret;
-		} else
-			dest += ret;
-		put_user(0, dest);
-		p = p->next;
-	}
-	restore_flags(flags);
-	return 0;
-}
-#endif
X 
X static int
X isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1315,6 +1386,17 @@
X 				} else
X 					return -EINVAL;
X 				break;
+#ifdef CONFIG_NETDEVICES
+			case IIOCNETGPN:
+				/* Get peer phone number of a connected 
+				 * isdn network interface */
+				if (arg) {
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+				} else
+					return -EINVAL;
+#endif
X 			default:
X 				return -EINVAL;
X 		}
@@ -1326,7 +1408,7 @@
X 		if (drvidx < 0)
X 			return -ENODEV;
X 		chidx = isdn_minor2chan(minor);
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
X 			return -ENODEV;
X 		return 0;
X 	}
@@ -1512,26 +1594,11 @@
X 				}
X 				if (drvidx == -1)
X 					return -ENODEV;
-				dev->drv[drvidx]->reject_bus = iocts.arg;
-				return 0;
-#if 0
-			case IIOCGETSET:
-				/* Get complete setup (all network-interfaces and profile-
-				   settings of all tty-devices */
-				if (arg)
-					return (isdn_get_allcfg((char *) arg));
+				if (iocts.arg)
+					dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
X 				else
-					return -EINVAL;
-				break;
-			case IIOCSETSET:
-				/* Set complete setup (all network-interfaces and profile-
-				   settings of all tty-devices */
-				if (arg)
-					return (isdn_set_allcfg((char *) arg));
-				else
-					return -EINVAL;
-				break;
-#endif
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 27'
echo 'File patch-2.3.4 is continued in part 28'
echo 28 > _shar_seq_.tmp
#!/bin/sh
# this is part 29 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 29; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+char *isdn_ppp_revision = "$Revision: 1.47 $";
X 
X static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
X static struct isdn_ppp_compressor *ipc_head = NULL;
X 
-extern int isdn_net_force_dial_lp(isdn_net_local *);
-
X /*
X  * frame log (debug)
X  */
X static void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen)
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
X {
X 	int cnt,
X 	 j,
@@ -223,13 +283,14 @@
X 	for (i = 0, cnt = 0; cnt < maxlen; i++) {
X 		for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
X 			sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
-		printk(KERN_DEBUG "%s[%d]: %s\n", info, i, buf);
+		printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
X 	}
X }
X 
X /*
X  * unbind isdn_net_local <=> ippp-device
X  * note: it can happen, that we hangup/free the master before the slaves
+ *       in this case we bind another lp to the master device
X  */
X int
X isdn_ppp_free(isdn_net_local * lp)
@@ -267,8 +328,7 @@
X 	if ((is->state & IPPP_CONNECT))
X 		isdn_ppp_closewait(lp->ppp_slot);	/* force wakeup on ippp device */
X 	else if (is->state & IPPP_ASSIGNED)
-		is->state = IPPP_OPEN;	/* fallback to 'OPEN but not ASSIGEND' staet */
-
+		is->state = IPPP_OPEN;	/* fallback to 'OPEN but not ASSIGNED' state */
X 
X 	if (is->debug & 0x1)
X 		printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
@@ -320,14 +380,16 @@
X 			}
X 		}
X 	} else {
-		for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-			if (ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == IPPP_OPEN)
+		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+			if (ippp_table[i]->minor == lp->pppbind &&
+			    (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
X 				break;
+		}
X 	}
X 
X 	if (i >= ISDN_MAX_CHANNELS) {
X 		restore_flags(flags);
-		printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
+		printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
X 		return -1;
X 	}
X 	unit = isdn_ppp_if_get_unit(lp->name);	/* get unit number from interface name .. ugly! */
@@ -336,6 +398,15 @@
X 		return -1;
X 	}
X 	lp->ppp_slot = i;
+
+	/* reset some values */
+	lp->netdev->ib.bundled = 0;
+	lp->netdev->ib.next_num = 0;
+	lp->netdev->ib.modify = 0;
+	lp->netdev->ib.last = NULL;
+	lp->netdev->ib.min = 0;
+	lp->netdev->ib.sq = NULL;
+
X 	is = ippp_table[i];
X 	is->lp = lp;
X 	is->unit = unit;
@@ -359,7 +430,10 @@
X 
X 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
X 
-	wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
+#if LINUX_VERSION_CODE < 131841
+	if (ippp_table[lp->ppp_slot]->wq)
+#endif
+		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
X }
X 
X /*
@@ -376,7 +450,11 @@
X 		return 0;
X 	is = ippp_table[slot];
X 
+#if LINUX_VERSION_CODE < 131841
+	if (is->state && is->wq)
+#else
X 	if (is->state)
+#endif
X 		wake_up_interruptible(&is->wq);
X 
X 	is->state = IPPP_CLOSEWAIT;
@@ -417,14 +495,19 @@
X 	}
X 	is = file->private_data = ippp_table[slot];
X 
+#if 0
X 	if (is->debug & 0x1)
+#endif
X 		printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
X 
X 	/* compression stuff */
-	is->compressor = NULL;
-	is->decomp_stat = is->comp_stat = NULL;
-	is->link_compressor = NULL;
-	is->link_decomp_stat = is->link_comp_stat = NULL;
+	is->link_compressor   = is->compressor = NULL;
+	is->link_decompressor = is->decompressor = NULL;
+	is->link_comp_stat    = is->comp_stat = NULL;
+	is->link_decomp_stat  = is->decomp_stat = NULL;
+	is->compflags = 0;
+
+	is->reset = isdn_ppp_ccp_reset_alloc(is);
X 
X 	is->lp = NULL;
X 	is->mp_seqno = 0;       /* MP sequence number */
@@ -436,9 +519,11 @@
X 	is->mru = 1524;         /* MRU, default 1524 */
X 	is->maxcid = 16;        /* VJ: maxcid */
X 	is->tk = current;
-	/* next two are redundant, but be paranoid */ 
-	init_waitqueue_head(&is->wq);  /* read() wait queue */
-	init_waitqueue_head(&is->wql);  /* select() wait queue */
+#if LINUX_VERSION_CODE < 131841
+	is->wq = NULL;          /* read() wait queue */
+#else
+	init_waitqueue_head(&is->wq);
+#endif
X 	is->first = is->rq + NUM_RCV_BUFFS - 1;	/* receive queue */
X 	is->last = is->rq;
X 	is->minor = min;
@@ -491,10 +576,30 @@
X 	is->last = is->rq;
X 
X #ifdef CONFIG_ISDN_PPP_VJ
+/* TODO: if this was the previous master: link the slcomp to the new master */
X 	slhc_free(is->slcomp);
X 	is->slcomp = NULL;
X #endif
X 
+/* TODO: if this was the previous master: link the the stuff to the new master */
+	if(is->comp_stat)
+		is->compressor->free(is->comp_stat);
+	if(is->link_comp_stat)
+		is->link_compressor->free(is->link_comp_stat);
+	if(is->link_decomp_stat)
+		is->link_decompressor->free(is->link_decomp_stat);
+	if(is->decomp_stat)
+		is->decompressor->free(is->decomp_stat);
+        is->compressor   = is->link_compressor   = NULL;
+        is->decompressor = is->link_decompressor = NULL;
+	is->comp_stat    = is->link_comp_stat    = NULL;
+        is->decomp_stat  = is->link_decomp_stat  = NULL;
+
+	if(is->reset)
+		kfree(is->reset);
+	is->reset = NULL;
+
+	/* this slot is ready for new connections */
X 	is->state = 0;
X }
X 
@@ -505,7 +610,7 @@
X get_arg(void *b, void *val, int len)
X {
X 	if (len <= 0)
-		len = sizeof(unsigned long);
+		len = sizeof(void *);
X 	if (copy_from_user((void *) val, b, len))
X 		return -EFAULT;
X 	return 0;
@@ -515,15 +620,12 @@
X  * set arg .. ioctl helper
X  */
X static int
-set_arg(void *b, unsigned long val, void *str)
+set_arg(void *b, void *val,int len)
X {
-	if (!str) {
-		if (copy_to_user(b, (void *) &val, 4))
-			return -EFAULT;
-	} else {
-		if (copy_to_user(b, str, val))
-			return -EFAULT;
-	}
+	if(len <= 0)
+		len = sizeof(void *);
+	if (copy_to_user(b, (void *) val, len))
+		return -EFAULT;
X 	return 0;
X }
X 
@@ -534,9 +636,10 @@
X isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
X {
X 	unsigned long val;
-	int num,r;
+	int r,i,j;
X 	struct ippp_struct *is;
X 	isdn_net_local *lp;
+	struct isdn_ppp_comp_data data;
X 
X 	is = (struct ippp_struct *) file->private_data;
X 	lp = is->lp;
@@ -552,7 +655,7 @@
X #ifdef CONFIG_ISDN_MPP
X 			if (!(is->state & IPPP_CONNECT))
X 				return -EINVAL;
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
X 				return r;
X 			printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
X 			       (int) min, (int) is->unit, (int) val);
@@ -562,24 +665,30 @@
X #endif
X 			break;
X 		case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-			if ((r = set_arg((void *) arg, is->unit, NULL)))
+			if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
+				return r;
+			break;
+		case PPPIOCGIFNAME:
+			if(!lp)
+				return -EINVAL;
+			if ((r = set_arg((void *) arg, lp->name,strlen(lp->name))))
X 				return r;
X 			break;
X 		case PPPIOCGMPFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, is->mpppcfg, NULL)))
+			if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
X 				return r;
X 			break;
X 		case PPPIOCSMPFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
X 				return r;
X 			is->mpppcfg = val;
X 			break;
X 		case PPPIOCGFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, is->pppcfg, NULL)))
+			if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
X 				return r;
X 			break;
X 		case PPPIOCSFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, 0))) {
+			if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
X 				return r;
X 			}
X 			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
@@ -598,12 +707,12 @@
X 			if (lp) {
X 				struct ppp_idle pidle;
X 				pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
-				if ((r = set_arg((void *) arg, sizeof(struct ppp_idle), &pidle)))
+				if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
X 					 return r;
X 			}
X 			break;
X 		case PPPIOCSMRU:	/* set receive unit size for PPP */
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
X 				return r;
X 			is->mru = val;
X 			break;
@@ -612,7 +721,7 @@
X 		case PPPIOCSMPMTU:
X 			break;
X 		case PPPIOCSMAXCID:	/* set the maximum compression slot id */
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
X 				return r;
X 			val++;
X 			if (is->maxcid != val) {
@@ -635,31 +744,33 @@
X 			}
X 			break;
X 		case PPPIOCGDEBUG:
-			if ((r = set_arg((void *) arg, is->debug, 0)))
+			if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
X 				return r;
X 			break;
X 		case PPPIOCSDEBUG:
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
X 				return r;
X 			is->debug = val;
X 			break;
X 		case PPPIOCGCOMPRESSORS:
X 			{
-				unsigned long protos = 0;
+				unsigned long protos[8] = {0,};
X 				struct isdn_ppp_compressor *ipc = ipc_head;
X 				while(ipc) {
-					protos |= (0x1<<ipc->num);
+					j = ipc->num / (sizeof(long)*8);
+					i = ipc->num % (sizeof(long)*8);
+					if(j < 8)
+						protos[j] |= (0x1<<i);
X 					ipc = ipc->next;
X 				}
-				if ((r = set_arg((void *) arg, protos, 0)))
+				if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
X 					return r;
X 			}
X 			break;
X 		case PPPIOCSCOMPRESSOR:
-			if ((r = get_arg((void *) arg, &num, sizeof(int))))
+			if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
X 				return r;
-			return isdn_ppp_set_compressor(is, num);
-			break;
+			return isdn_ppp_set_compressor(is, &data);
X 		case PPPIOCGCALLINFO:
X 			{
X 				struct pppcallinfo pci;
@@ -678,7 +789,7 @@
X 					if(lp->flags & ISDN_NET_CALLBACK)
X 						pci.calltype |= CALLTYPE_CALLBACK;
X 				}
-				return set_arg((void *)arg,sizeof(struct pppcallinfo),&pci);
+				return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
X 			}
X 		default:
X 			break;
@@ -701,9 +812,12 @@
X 		printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
X 				MINOR(file->f_dentry->d_inode->i_rdev));
X 
+	/* just registers wait_queue hook. This doesn't really wait. */
X 	poll_wait(file, &is->wq, wait);
X 
X 	if (!(is->state & IPPP_OPEN)) {
+		if(is->state == IPPP_CLOSEWAIT)
+			return POLLHUP;
X 		printk(KERN_DEBUG "isdn_ppp: device not open\n");
X 		return POLLERR;
X 	}
@@ -777,7 +891,10 @@
X 	is->last = bl->next;
X 	restore_flags(flags);
X 
-	wake_up_interruptible(&is->wq);
+#if LINUX_VERSION_CODE < 131841
+	if (is->wq)
+#endif
+		wake_up_interruptible(&is->wq);
X 
X 	return len;
X }
@@ -863,7 +980,8 @@
X 		if (lp->isdn_device < 0 || lp->isdn_channel < 0)
X 			return 0;
X 
-		if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
+		if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
+			lp->dialstate == 0 &&
X 		    (lp->flags & ISDN_NET_CONNECTED)) {
X 			int cnt;
X 			struct sk_buff *skb;
@@ -876,8 +994,11 @@
X 				return -EFAULT;
X 			if (is->debug & 0x40) {
X 				printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
-				isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
+				isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
X 			}
+
+			isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
+
X 			if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
X 				if (lp->sav_skb) {
X 					dev_kfree_skb(lp->sav_skb);
@@ -910,8 +1031,6 @@
X 			return -1;
X 		}
X 		memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
-		init_waitqueue_head(&ippp_table[i]->wq); 
-		init_waitqueue_head(&ippp_table[i]->wql); 
X 		ippp_table[i]->state = 0;
X 		ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
X 		ippp_table[i]->last = ippp_table[i]->rq;
@@ -963,8 +1082,9 @@
X 	is = ippp_table[lp->ppp_slot];
X 
X 	if (is->debug & 0x4) {
-		printk(KERN_DEBUG "ippp_receive: len: %d\n", (int) skb->len);
-		isdn_ppp_frame_log("receive", skb->data, skb->len, 32);
+		printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
+		       (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);
+		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
X 	}
X 	if (net_dev->local->master) {
X 		printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
@@ -982,13 +1102,18 @@
X #ifdef CONFIG_ISDN_MPP
X 	if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
X 		int sqno_end;
-		
-		if(proto == PPP_LINK_COMP) {
-			printk(KERN_DEBUG "received single link compressed frame\n");
-			skb = isdn_ppp_decompress(skb,is,NULL);
-			if(!skb)
-				return;
-			proto = isdn_ppp_strip_proto(skb);
+
+		if(is->compflags & SC_LINK_DECOMP_ON) {	
+			if(proto == PPP_LINK_COMP) {
+				if(is->debug & 0x10)
+					printk(KERN_DEBUG "received single link compressed frame\n");
+				skb = isdn_ppp_decompress(skb,is,NULL,proto);
+				if(!skb)
+					return;
+				proto = isdn_ppp_strip_proto(skb);
+			}
+			else
+				isdn_ppp_decompress(skb,is,NULL,proto);
X 		}
X 
X 		if (proto == PPP_MP) {
@@ -1055,7 +1180,8 @@
X 				}
X 				min_sqno &= mask;
X 				for (lpq = net_dev->queue;;) {
-					ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
+					if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0)
+						ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
X 					lpq = lpq->next;
X 					if (lpq == net_dev->queue)
X 						break;
@@ -1150,17 +1276,31 @@
X 
X 	if (is->debug & 0x10) {
X 		printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
-		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32);
+		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
X 	}
X 
X 	if(proto == PPP_COMP) {
X 		if(!lp->master)
-			skb = isdn_ppp_decompress(skb,is,is);
+			skb = isdn_ppp_decompress(skb,is,is,proto);
X 		else
-			skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]);
-		if(!skb)
+			skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
+
+		if(!skb) {
+			printk(KERN_DEBUG "ippp: compressed frame discarded!\n");
X 			return;
+		}
+
X 		proto = isdn_ppp_strip_proto(skb);
+		if (is->debug & 0x10) {
+			printk(KERN_DEBUG "RPostDecomp, skb %d %04x\n", (int) skb->len, proto);
+			isdn_ppp_frame_log("R-Decomp", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
+		}
+	}
+	else if(is->compflags & SC_DECOMP_ON)  { /* If decomp is ON */
+		if(!lp->master)
+			isdn_ppp_decompress(skb,is,is,proto);
+		else
+			isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
X 	}
X 
X 	switch (proto) {
@@ -1227,7 +1367,13 @@
X #endif
X 			break;
X 		case PPP_CCP:
-			isdn_ppp_receive_ccp(net_dev,lp,skb);
+		case PPP_LINK_CCP:
+			isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
+			/* Dont pop up ResetReq/Ack stuff to the daemon any
+			   longer - the job is done already */
+			if(skb->data[0] == CCP_RESETREQ ||
+			   skb->data[0] == CCP_RESETACK)
+				break;
X 			/* fall through */
X 		default:
X 			isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);	/* push data to pppd device */
@@ -1235,10 +1381,10 @@
X 			return;
X 	}
X 
+ 	/* Reset hangup-timer */
+ 	lp->huptimer = 0;
X 	netif_rx(skb);
X 	/* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */
-	/* Reset hangup-timer */
-	lp->huptimer = 0;
X 
X 	return;
X }
@@ -1339,7 +1485,6 @@
X 		lp = nlp;
X 	}
X 	ipt = ippp_table[lp->ppp_slot];
-
X 	lp->huptimer = 0;
X 
X 	/*
@@ -1355,6 +1500,8 @@
X 
X 	if (ipt->debug & 0x4)
X 		printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
+        if (ipts->debug & 0x40)
+                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);
X 
X #ifdef CONFIG_ISDN_PPP_VJ
X 	if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes, but check this again */
@@ -1394,10 +1541,11 @@
X 	}
X #endif
X 
-    /*
-     * normal or bundle compression
-     */
-	skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+	/*
+	 * normal (single link) or bundle compression
+	 */
+	if(ipts->compflags & SC_COMP_ON)
+		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
X 
X 	if (ipt->debug & 0x24)
X 		printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
@@ -1431,9 +1579,10 @@
X #endif
X 
X 	/*
-	 * 'link' compression 
+	 * 'link in bundle' compression  ...
X 	 */
-	skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+	if(ipt->compflags & SC_LINK_COMP_ON)
+		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
X 
X 	if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
X 		unsigned char *data = isdn_ppp_skb_push(&skb,1);
@@ -1460,7 +1609,7 @@
X 
X 	if (ipts->debug & 0x40) {
X 		printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
-		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
+		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
X 	}
X 	if (isdn_net_send_skb(dev, lp, skb)) {
X 		if (lp->sav_skb) {	/* whole sav_skb processing with disabled IRQs ?? */
@@ -1474,6 +1623,12 @@
X 
X #ifdef CONFIG_ISDN_MPP
X 
+/*
+ * free SQ queue
+ * -------------
+ * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames,
+ * that can't be delivered, because there is an outstanding earlier frame
+ */
X static void
X isdn_ppp_free_sqqueue(isdn_net_dev * p)
X {
@@ -1490,6 +1645,12 @@
X 
X }
X 
+/*
+ * free MP queue
+ * -------------
+ * Note: The MP queue holds all frame fragments of frames, that can't be
+ * reassembled, because there is at least one missing fragment.
+ */
X static void 
X isdn_ppp_free_mpqueue(isdn_net_dev * p)
X {
@@ -1551,7 +1712,9 @@
X 	return 0;
X }
X 
-
+/*
+ * Mask sequence numbers in MP queue
+ */
X static void
X isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
X {
@@ -1562,6 +1725,11 @@
X 	}
X }
X 
+/*
+ * put a fragment at the right place into the MP queue 
+ * Also checks, whether this fragment completes a frame. In this case
+ * the fragments are copied together into one SKB
+ */
X static int
X isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno)
X {
@@ -1762,13 +1930,11 @@
X 		slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp);
X #endif
X }
+#endif
X 
X /*
X  * a buffered packet timed-out?
X  */
-
-#endif
-
X void
X isdn_ppp_timer_timeout(void)
X {
@@ -1940,7 +2106,7 @@
X 	if (!sdev)
X 		return 2;
X 
-	isdn_net_force_dial_lp((isdn_net_local *) sdev->priv);
+	isdn_net_dial_req((isdn_net_local *) sdev->priv);
X 	return 0;
X #else
X 	return -1;
@@ -1981,47 +2147,440 @@
X /*
X  * PPP compression stuff
X  */
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master)
+
+
+/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
+   generate a CCP Reset-Request or tear down CCP altogether */
+
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
+{
+	isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
+}
+
+/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
+   but absolutely nontrivial. The most abstruse problem we are facing is
+   that the generation, reception and all the handling of timeouts and
+   resends including proper request id management should be entirely left
+   to the (de)compressor, but indeed is not covered by the current API to
+   the (de)compressor. The API is a prototype version from PPP where only
+   some (de)compressors have yet been implemented and all of them are
+   rather simple in their reset handling. Especially, their is only one
+   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
+   not have parameters. For this very special case it was sufficient to
+   just return an error code from the decompressor and have a single
+   reset() entry to communicate all the necessary information between
+   the framework and the (de)compressor. Bad enough, LZS is different
+   (and any other compressor may be different, too). It has multiple
+   histories (eventually) and needs to Reset each of them independently
+   and thus uses multiple outstanding Acks and history numbers as an
+   additional parameter to Reqs/Acks.
+   All that makes it harder to port the reset state engine into the
+   kernel because it is not just the same simple one as in (i)pppd but
+   it must be able to pass additional parameters and have multiple out-
+   standing Acks. We are trying to achieve the impossible by handling
+   reset transactions independent by their id. The id MUST change when
+   the data portion changes, thus any (de)compressor who uses more than
+   one resettable state must provide and recognize individual ids for
+   each individual reset transaction. The framework itself does _only_
+   differentiate them by id, because it has no other semantics like the
+   (de)compressor might.
+   This looks like a major redesign of the interface would be nice,
+   but I don't have an idea how to do it better. */
+
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
+   getting that lengthy because there is no simple "send-this-frame-out"
+   function above but every wrapper does a bit different. Hope I guess
+   correct in this hack... */
+
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+				    unsigned char code, unsigned char id,
+				    unsigned char *data, int len)
+{
+	struct sk_buff *skb;
+	unsigned char *p;
+	int count;
+	int cnt = 0;
+	isdn_net_local *lp = is->lp;
+
+	/* Alloc large enough skb */
+	skb = dev_alloc_skb(len + 16);
+	if(!skb) {
+		printk(KERN_WARNING
+		       "ippp: CCP cannot send reset - out of memory\n");
+		return;
+	}
+
+	/* We may need to stuff an address and control field first */
+	if(!(is->pppcfg & SC_COMP_AC)) {
+		p = skb_put(skb, 2);
+		*p++ = 0xff;
+		*p++ = 0x03;
+	}
+
+	/* Stuff proto, code, id and length */
+	p = skb_put(skb, 6);
+	*p++ = (proto >> 8);
+	*p++ = (proto & 0xff);
+	*p++ = code;
+	*p++ = id;
+	cnt = 4 + len;
+	*p++ = (cnt >> 8);
+	*p++ = (cnt & 0xff);
+
+	/* Now stuff remaining bytes */
+	if(len) {
+		p = skb_put(skb, len);
+		memcpy(p, data, len);
+	}
+
+	/* skb is now ready for xmit */
+	printk(KERN_DEBUG "Sending CCP Frame:\n");
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+	/* Just ripped from isdn_ppp_write. Dunno whether it makes sense,
+	   especially dunno what the sav_skb stuff is good for. */
+
+	count = skb->len;
+	if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel,
+					  1, skb)) != count) {
+		if (lp->sav_skb) {
+			dev_kfree_skb(lp->sav_skb);
+			printk(KERN_INFO
+			       "isdn_ppp_write: freeing sav_skb (%d,%d)!\n",
+			       cnt, count);
+		} else
+			printk(KERN_INFO
+			       "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n",
+			       cnt, count);
+		lp->sav_skb = skb;
+	}
+}
+
+/* Allocate the reset state vector */
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
+{
+	struct ippp_ccp_reset *r;
+	printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n");
+	r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+	if(!r)
+		return NULL;
+	memset(r, 0, sizeof(struct ippp_ccp_reset));
+	is->reset = r;
+	return r;
+}
+
+/* Free a given state and clear everything up for later reallocation */
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+					  unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	if(is->reset->rs[id]) {
+		printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
+		rs = is->reset->rs[id];
+		/* Make sure the kernel will not call back later */
+		if(rs->ta)
+			del_timer(&rs->timer);
+		is->reset->rs[id] = NULL;
+		kfree(rs);
+	} else {
+		printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
+	}
+}
+
+/* The timer callback function which is called when a ResetReq has timed out,
+   aka has never been answered by a ResetAck */
+static void isdn_ppp_ccp_timer_callback(unsigned long closure)
+{
+	struct ippp_ccp_reset_state *rs =
+		(struct ippp_ccp_reset_state *)closure;
+
+	if(!rs) {
+		printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
+		return;
+	}
+	if(rs->ta && rs->state == CCPResetSentReq) {
+		/* We are correct here */
+		printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+		       rs->id);
+		if(!rs->expra) {
+			/* Hmm, there is no Ack really expected. We can clean
+			   up the state now, it will be reallocated if the
+			   decompressor insists on another reset */
+			rs->ta = 0;
+			isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
+			return;
+		}
+		/* Push it again */
+		isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
+					rs->data, rs->dlen);
+		/* Restart timer */
+		rs->timer.expires = jiffies + HZ*5;
+		add_timer(&rs->timer);
+	} else {
+		printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
+		       rs->state);
+	}
+}
+
+/* Allocate a new reset transaction state */
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+						      unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs;
+	if(is->reset->rs[id]) {
+		printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
+		       id);
+		return NULL;
+	} else {
+		rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+		if(!rs)
+			return NULL;
+		memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
+		rs->state = CCPResetIdle;
+		rs->is = is;
+		rs->id = id;
+		rs->timer.data = (unsigned long)rs;
+		rs->timer.function = isdn_ppp_ccp_timer_callback;
+		is->reset->rs[id] = rs;
+	}
+	return rs;
+}
+
+
+/* A decompressor wants a reset with a set of parameters - do what is
+   necessary to fulfill it */
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+				     struct isdn_ppp_resetparams *rp)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	if(rp->valid) {
+		/* The decompressor defines parameters by itself */
+		if(rp->rsend) {
+			/* And he wants us to send a request */
+			if(!(rp->idval)) {
+				printk(KERN_ERR "ippp_ccp: decompressor must"
+				       " specify reset id\n");
+				return;
+			}
+			if(is->reset->rs[rp->id]) {
+				/* There is already a transaction in existence
+				   for this id. May be still waiting for a
+				   Ack or may be wrong. */
+				rs = is->reset->rs[rp->id];
+				if(rs->state == CCPResetSentReq && rs->ta) {
+					printk(KERN_DEBUG "ippp_ccp: reset"
+					       " trans still in progress"
+					       " for id %d\n", rp->id);
+				} else {
+					printk(KERN_WARNING "ippp_ccp: reset"
+					       " trans in wrong state %d for"
+					       " id %d\n", rs->state, rp->id);
+				}
+			} else {
+				/* Ok, this is a new transaction */
+				printk(KERN_DEBUG "ippp_ccp: new trans for id"
+				       " %d to be started\n", rp->id);
+				rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
+				if(!rs) {
+					printk(KERN_ERR "ippp_ccp: out of mem"
+					       " allocing ccp trans\n");
+					return;
+				}
+				rs->state = CCPResetSentReq;
+				rs->expra = rp->expra;
+				if(rp->dtval) {
+					rs->dlen = rp->dlen;
+					memcpy(rs->data, rp->data, rp->dlen);
+				}
+				/* HACK TODO - add link comp here */
+				isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
+							CCP_RESETREQ, rs->id,
+							rs->data, rs->dlen);
+				/* Start the timer */
+				rs->timer.expires = jiffies + 5*HZ;
+				add_timer(&rs->timer);
+				rs->ta = 1;
+			}
+		} else {
+			printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
+		}
+	} else {
+		/* The reset params are invalid. The decompressor does not
+		   care about them, so we just send the minimal requests
+		   and increase ids only when an Ack is received for a
+		   given id */
+		if(is->reset->rs[is->reset->lastid]) {
+			/* There is already a transaction in existence
+			   for this id. May be still waiting for a
+			   Ack or may be wrong. */
+			rs = is->reset->rs[is->reset->lastid];
+			if(rs->state == CCPResetSentReq && rs->ta) {
+				printk(KERN_DEBUG "ippp_ccp: reset"
+				       " trans still in progress"
+				       " for id %d\n", rp->id);
+			} else {
+				printk(KERN_WARNING "ippp_ccp: reset"
+				       " trans in wrong state %d for"
+				       " id %d\n", rs->state, rp->id);
+			}
+		} else {
+			printk(KERN_DEBUG "ippp_ccp: new trans for id"
+			       " %d to be started\n", is->reset->lastid);
+			rs = isdn_ppp_ccp_reset_alloc_state(is,
+							    is->reset->lastid);
+			if(!rs) {
+				printk(KERN_ERR "ippp_ccp: out of mem"
+				       " allocing ccp trans\n");
+				return;
+			}
+			rs->state = CCPResetSentReq;
+			/* We always expect an Ack if the decompressor doesnt
+			   know	better */
+			rs->expra = 1;
+			rs->dlen = 0;
+			/* HACK TODO - add link comp here */
+			isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
+						rs->id, NULL, 0);
+			/* Start the timer */
+			rs->timer.expires = jiffies + 5*HZ;
+			add_timer(&rs->timer);
+			rs->ta = 1;
+		}
+	}
+}
+
+/* An Ack was received for this id. This means we stop the timer and clean
+   up the state prior to calling the decompressors reset routine. */
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+					unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs = is->reset->rs[id];
+
+	if(rs) {
+		if(rs->ta && rs->state == CCPResetSentReq) {
+			/* Great, we are correct */
+			if(!rs->expra)
+				printk(KERN_DEBUG "ippp_ccp: ResetAck received"
+				       " for id %d but not expected\n", id);
+		} else {
+			printk(KERN_INFO "ippp_ccp: ResetAck received out of"
+			       "sync for id %d\n", id);
+		}
+		if(rs->ta) {
+			rs->ta = 0;
+			del_timer(&rs->timer);
+		}
+		isdn_ppp_ccp_reset_free_state(is, id);
+	} else {
+		printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
+		       " %d\n", id);
+	}
+	/* Make sure the simple reset stuff uses a new id next time */
+	is->reset->lastid++;
+}
+
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
+	int proto)
X {
-#if 1
-	printk(KERN_ERR "compression not included!\n");
-	dev_kfree_skb(skb);
-	return NULL;
+#ifndef CONFIG_ISDN_CCP
+	if(proto == PPP_COMP || proto == PPP_LINK_COMP) {
+		printk(KERN_ERR "isdn_ppp: Ouch! Compression not included!\n");
+		dev_kfree_skb(skb);
+		return NULL;
+	}
+	return skb;
X #else
+	void *stat = NULL;
+	struct isdn_ppp_compressor *ipc = NULL;
+	struct sk_buff *skb_out;
+	int len;
+	struct ippp_struct *ri;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
X 	if(!master) {
X 		/* 
-		 * single link compression 
+		 * single link decompression 
X 		 */
-		if(!is->link_compressor) {
-			printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+		if(!is->link_decompressor) {
+			printk(KERN_ERR "ippp: no link decompressor defined!\n");
X 			dev_kfree_skb(skb);
X 			return NULL;
X 		}
X 		if(!is->link_decomp_stat) {
-			printk(KERN_DEBUG "ippp: initialize link compressor\n");
+			printk(KERN_DEBUG "ippp: no link decompressor data allocated\n");
+			dev_kfree_skb(skb);
+			return NULL;
X 		}
-/*
-		-> decompress link
-*/
-    }
+		stat = is->link_decomp_stat;
+		ipc = is->link_decompressor;
+		ri = is;
+	}
X 	else {
X 		/*
X 		 * 'normal' or bundle-compression 
X 		 */
-		if(!master->compressor) {
-			printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+		if(!master->decompressor) {
+			printk(KERN_ERR "ippp: no decompressor defined!\n");
X 			dev_kfree_skb(skb);
X 			return NULL;
X 		}
X 		if(!master->decomp_stat) {
-#if 0
-			master->decomp_stat = (master->compressor->decomp_alloc)( .. );
-#endif
-			printk(KERN_DEBUG "ippp: initialize compressor\n");
+			printk(KERN_DEBUG "ippp: no decompressor data allocated\n");
+			dev_kfree_skb(skb);
+			return NULL;
X 		}
+		stat = master->decomp_stat;
+		ipc = master->decompressor;
+		ri = master;
+	}
+
+	/*
+	printk(KERN_DEBUG "ippp: Decompress valid!\n");
+	*/
+
+	if((master && proto == PPP_COMP) || (!master && proto == PPP_LINK_COMP) ) {
+		/* Set up reset params for the decompressor */
+		memset(&rsparm, 0, sizeof(rsparm));
+		rsparm.data = rsdata;
+		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+
+/* !!!HACK,HACK,HACK!!! 2048 is only assumed */
+		skb_out = dev_alloc_skb(2048);
+		len = ipc->decompress(stat,skb,skb_out, &rsparm);
+		dev_kfree_skb(skb);
+		if(len <= 0) {
+		  /* Ok, some error */
+		  switch(len) {
+		  case DECOMP_ERROR:
+		    ri->pppcfg |= SC_DC_ERROR;
+		    printk(KERN_INFO "ippp: decomp wants reset %s params\n",
+			   rsparm.valid ? "with" : "without");
+
+		    isdn_ppp_ccp_reset_trans(ri, &rsparm);
+
+		    break;
+		  case DECOMP_FATALERROR:
+		    ri->pppcfg |= SC_DC_FERROR;
+		    /* Kick ipppd to recognize the error */
+		    isdn_ppp_ccp_kickup(ri);
+		    break;
+		  }
+		  /* Did I see a leak here ? */
+		  dev_kfree_skb(skb_out);
+		  return NULL;
+		}
+		return skb_out;
+	}
+	else {
+		/*
+		printk(KERN_DEBUG "isdn_ppp: [%d] Calling incomp with this frame!\n",is->unit);
+		*/
+		ipc->incomp(stat,skb,proto);
+		return skb;
X 	}
-	
-	return skb;
X #endif
X }
X 
@@ -2035,19 +2594,29 @@
X static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
X 	struct ippp_struct *is,struct ippp_struct *master,int type)
X {
-#if 1	
-	return skb_in;
-#else
X     int ret;
X     int new_proto;
X     struct isdn_ppp_compressor *compressor;
X     void *stat;
X     struct sk_buff *skb_out;
X 
+#ifdef CONFIG_ISDN_CCP
+	/* we do not compress control protocols */
+    if(*proto < 0 || *proto > 0x3fff) {
+#else
+    {
+#endif
+      return skb_in;
+    }
+
X 	if(type) { /* type=1 => Link compression */
+#if 0
X 		compressor = is->link_compressor;
X 		stat = is->link_comp_stat;
X 		new_proto = PPP_LINK_COMP;
+#else
+		return skb_in;
+#endif
X 	}
X 	else {
X 		if(!master) {
@@ -2062,15 +2631,16 @@
X 	}
X 
X 	if(!compressor) {
-		printk(KERN_ERR "No compressor set!\n");
+		printk(KERN_ERR "isdn_ppp: No compressor set!\n");
X 		return skb_in;
X 	}
X 	if(!stat) {
-		/* init here ? */
+		printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
X 		return skb_in;
X 	}
X 
-	skb_out = dev_alloc_skb(skb_in->len);
+	/* Allow for at least 150 % expansion (for now) */
+	skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32);
X 	if(!skb_out)
X 		return skb_in;
X 
@@ -2083,24 +2653,225 @@
X 	dev_kfree_skb(skb_in);
X 	*proto = new_proto;
X 	return skb_out;
-#endif
-
X }
X 
X /*
X  * we received a CCP frame .. 
- * not a clean solution, but we SHOULD handle a few cased in the kernel
+ * not a clean solution, but we MUST handle a few cases in the kernel
X  */
X static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
-	 struct sk_buff *skb)
+	 struct sk_buff *skb,int proto)
X {
-#if 0
-	printk(KERN_DEBUG "isdn_ppp_receive_cpp: %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		skb->data[0],skb->data[1],skb->data[2],skb->data[3],
-		skb->data[4],skb->data[5],skb->data[6],skb->data[7] );
-#endif
+	struct ippp_struct *is = ippp_table[lp->ppp_slot];
+	struct ippp_struct *mis;
+	int len;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
+
+	printk(KERN_DEBUG "Received CCP frame from peer\n");
+	isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+	if(lp->master)
+		mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
+	else
+		mis = is;
+
+	switch(skb->data[0]) {
+	case CCP_CONFREQ:
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+		if(proto == PPP_CCP)
+			mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);		
+		else
+			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);		
+		break;
+	case CCP_CONFACK:
+		/* if we RECEIVE an ackowledge we enable the decompressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Enable decompression here!\n");
+		if(proto == PPP_CCP)
+			mis->compflags |= SC_DECOMP_ON;
+		else
+			is->compflags |= SC_LINK_DECOMP_ON;
+		break;
+
+	case CCP_RESETACK:
+		printk(KERN_DEBUG "Received ResetAck from peer\n");
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+
+		if(proto == PPP_CCP) {
+			/* If a reset Ack was outstanding for this id, then
+			   clean up the state engine */
+			isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
+			if(mis->decompressor && mis->decomp_stat)
+				mis->decompressor->
+					reset(mis->decomp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, NULL);
+			/* TODO: This is not easy to decide here */
+			mis->compflags &= ~SC_DECOMP_DISCARD;
+			mis->pppcfg &= ~SC_DC_ERROR;
+		}
+		else {
+			isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
+			if(is->link_decompressor && is->link_decomp_stat)
+				is->link_decompressor->
+					reset(is->link_decomp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, NULL);
+			/* TODO: neither here */
+			is->compflags &= ~SC_LINK_DECOMP_DISCARD;
+			is->pppcfg &= ~SC_DC_ERROR;
+		}
+		break;
+
+	case CCP_RESETREQ:
+		printk(KERN_DEBUG "Received ResetReq from peer\n");
+		/* Receiving a ResetReq means we must reset our compressor */
+		/* Set up reset params for the reset entry */
+		memset(&rsparm, 0, sizeof(rsparm));
+		rsparm.data = rsdata;
+		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; 
+		/* Isolate data length */
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+		if(proto == PPP_CCP) {
+			if(mis->compressor && mis->comp_stat)
+				mis->compressor->
+					reset(mis->comp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, &rsparm);
+		}
+		else {
+			if(is->link_compressor && is->link_comp_stat)
+				is->link_compressor->
+					reset(is->link_comp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, &rsparm);
+		}
+		/* Ack the Req as specified by rsparm */
+		if(rsparm.valid) {
+			/* Compressor reset handler decided how to answer */
+			if(rsparm.rsend) {
+				/* We should send a Frame */
+				isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+							rsparm.idval ? rsparm.id
+							: skb->data[1],
+							rsparm.dtval ?
+							rsparm.data : NULL,
+							rsparm.dtval ?
+							rsparm.dlen : 0);
+			} else {
+				printk(KERN_DEBUG "ResetAck suppressed\n");
+			}
+		} else {
+			/* We answer with a straight reflected Ack */
+			isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+						skb->data[1],
+						len ? &skb->data[4] : NULL,
+						len);
+		}
+		break;
+	}
X }
X 
+
+/*
+ * Daemon sends a CCP frame ...
+ */
+
+/* TODO: Clean this up with new Reset semantics */
+
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
+{
+	struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
+	int proto;
+	unsigned char *data;
+
+	if(!skb || skb->len < 3)
+		return;
+
+	/* Daemon may send with or without address and control field comp */
+	data = skb->data;
+	if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
+		data += 2;
+		if(skb->len < 5)
+			return;
+	}
+
+	proto = ((int)data[0]<<8)+data[1];
+	if(proto != PPP_CCP && proto != PPP_LINK_CCP)
+		return;
+
+	printk(KERN_DEBUG "Received CCP frame from daemon:\n");
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+        if(lp->master)
+                mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
+        else
+                mis = is;
+	
+	if(mis != is)
+		printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
+	
+        switch(data[2]) {
+	case CCP_CONFREQ:
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+		if(proto == PPP_CCP)
+			is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+		else
+			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
+		break;
+	case CCP_CONFACK:
+		/* if we SEND an ackowledge we can/must enable the compressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Enable compression here!\n");
+		if(proto == PPP_CCP)
+			is->compflags |= SC_COMP_ON;
+		else
+			is->compflags |= SC_LINK_COMP_ON;
+		break;
+	case CCP_RESETACK:
+		/* If we send a ACK we should reset our compressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Reset decompression state here!\n");
+		printk(KERN_DEBUG "ResetAck from daemon passed by\n");
+		if(proto == PPP_CCP) {
+			/* link to master? */
+			if(is->compressor && is->comp_stat)
+				is->compressor->reset(is->comp_stat, 0, 0,
+						      NULL, 0, NULL);
+			is->compflags &= ~SC_COMP_DISCARD;	
+		}
+		else {
+			if(is->link_compressor && is->link_comp_stat)
+				is->link_compressor->reset(is->link_comp_stat,
+							   0, 0, NULL, 0, NULL);
+			is->compflags &= ~SC_LINK_COMP_DISCARD;	
+		}
+		break;
+	case CCP_RESETREQ:
+		/* Just let it pass by */
+		printk(KERN_DEBUG "ResetReq from daemon passed by\n");
+		break;
+	}
+}
+
+
X int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
X {
X 	ipc->next = ipc_head;
@@ -2124,32 +2895,67 @@
X 	return 0;
X }
X 
-static int isdn_ppp_set_compressor(struct ippp_struct *is,int num)
+static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
X {
X 	struct isdn_ppp_compressor *ipc = ipc_head;
+	int ret;
+	void *stat;
+	int num = data->num;
+
+	if(is->debug & 0x10)
+		printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
+			(data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
X 
X 	while(ipc) {
X 		if(ipc->num == num) {
-			return 0;	
-			is->compressor = ipc;
-			is->link_compressor = ipc;
+			stat = ipc->alloc(data);
+			if(stat) {
+				ret = ipc->init(stat,data,is->unit,0);
+				if(!ret) {
+					printk(KERN_ERR "Can't init (de)compression!\n");
+					ipc->free(stat);
+					stat = NULL;
+					break;
+				}
+			}
+			else {
+				printk(KERN_ERR "Can't alloc (de)compression!\n");
+				break;
+			}
+
+                        if(data->flags & IPPP_COMP_FLAG_XMIT) {
+				if(data->flags & IPPP_COMP_FLAG_LINK) {
+					if(is->link_comp_stat)
+						is->link_compressor->free(is->link_comp_stat);
+					is->link_comp_stat = stat;
+                                	is->link_compressor = ipc;
+				}
+				else {
+					if(is->comp_stat)
+						is->compressor->free(is->comp_stat);
+					is->comp_stat = stat;
+                                	is->compressor = ipc;
+				}
+			}
+                        else {
+				if(data->flags & IPPP_COMP_FLAG_LINK) {
+					if(is->link_decomp_stat)
+						is->link_decompressor->free(is->link_decomp_stat);
+					is->link_decomp_stat = stat;
+        	                        is->link_decompressor = ipc;
+				}
+				else {
+					if(is->decomp_stat)
+						is->decompressor->free(is->decomp_stat);
+					is->decomp_stat = stat;
+        	                        is->decompressor = ipc;
+				}
+			}
+			return 0;
X 		}
X 		ipc = ipc->next;
X 	}
X 	return -EINVAL;
X }
-
-
-#if 0
-static struct symbol_table isdn_ppp_syms =
-{
-#include <linux/symtab_begin.h>
-	X(isdn_ppp_register_compressor),
-	X(isdn_ppp_unregister_compressor),
-#include <linux/symtab_end.h>
-};
-#endif
-
-
X 
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h
--- v2.3.3/linux/drivers/isdn/isdn_ppp.h	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_ppp.h	Sun May 23 10:03:42 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.h,v 1.12 1998/01/31 22:07:48 keil Exp $
+/* $Id: isdn_ppp.h,v 1.13 1998/03/22 18:50:50 hipp Exp $
X 
X  * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
X  *
@@ -19,6 +19,9 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_ppp.h,v $
+ * Revision 1.13  1998/03/22 18:50:50  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
X  * Revision 1.12  1998/01/31 22:07:48  keil
X  * changes for newer kernels
X  *
@@ -83,6 +86,9 @@
X extern void isdn_ppp_release(int, struct file *);
X extern int isdn_ppp_dial_slave(char *);
X extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
+
+extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
+extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
X 
X #define IPPP_OPEN	0x01
X #define IPPP_CONNECT	0x02
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.3.3/linux/drivers/isdn/isdn_tty.c	Fri May 14 18:55:19 1999
+++ linux/drivers/isdn/isdn_tty.c	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_tty.c,v 1.47 1998/02/22 19:44:14 fritz Exp $
+/* $Id: isdn_tty.c,v 1.63 1999/04/12 12:33:39 fritz Exp $
X 
X  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fr...@isdn4linux.de)
X  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,73 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_tty.c,v $
+ * Revision 1.63  1999/04/12 12:33:39  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.62 1999/03/02 12:04:48 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.61  1999/01/27 22:53:11  he
+ * minor updates (spellings, jiffies wrap around in isdn_tty)
+ *
+ * Revision 1.60  1998/11/15 23:57:32  keil
+ * changes for 2.1.127
+ *
+ * Revision 1.59  1998/08/20 13:50:15  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.58  1998/07/26 18:48:45  armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.57 1998/06/26 15:12:36 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.56  1998/06/18 23:31:51  fritz
+ * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
+ * Removed direct-senddown feature in isdn_tty_write because it will
+ * never succeed with locking and is useless anyway.
+ *
+ * Revision 1.55  1998/06/17 19:50:55  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.54 1998/06/07 00:20:13 fritz
+ * abc cleanup.
+ *
+ * Revision 1.53 1998/06/02 12:10:16 detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.52 1998/03/19 13:18:21 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 1.51  1998/03/08 14:26:11  detabc
+ * change kfree_skb to dev_kfree_skb
+ * remove SET_SKB_FREE
+ *
+ * Revision 1.50  1998/03/08 13:14:28  detabc
+ * abc-extension support for kernels > 2.1.x
+ * first try (sorry experimental)
+ *
+ * Revision 1.49  1998/03/08 00:01:59  fritz
+ * Bugfix: Lowlevel module usage and channel usage were not
+ *         reset on NO DCHANNEL.
+ *
+ * Revision 1.48  1998/03/07 12:28:15  tsbogend
+ * fixed kernel unaligned traps on Linux/Alpha
+ *
X  * Revision 1.47  1998/02/22 19:44:14  fritz
X  * Bugfixes and improvements regarding V.110, V.110 now running.
X  *
@@ -254,7 +321,7 @@
X static int si2bit[8] =
X {4, 1, 4, 4, 4, 4, 4, 4};
X 
-char *isdn_tty_revision = "$Revision: 1.47 $";
+char *isdn_tty_revision = "$Revision: 1.63 $";
X 
X #define DLE 0x10
X #define ETX 0x03
@@ -270,6 +337,8 @@
X #define REG_LF        4
X #define REG_BS        5
X 
+#define REG_WAITC     7
+
X #define REG_RESP     12
X #define BIT_RESP      1
X #define REG_RESPNUM  12
@@ -287,8 +356,6 @@
X #define REG_CPPP     12
X #define BIT_CPPP    128
X 
-#define REG_DELXMT   13
-#define BIT_DELXMT    1
X #define REG_T70      13
X #define BIT_T70       2
X #define BIT_T70_EXT  32
@@ -300,6 +367,8 @@
X #define BIT_CIDONCE  16
X #define REG_RUNG     13
X #define BIT_RUNG     64
+#define REG_RESRXT   13
+#define BIT_RESRXT  128
X 
X #define REG_L2PROT   14
X #define REG_L3PROT   15
@@ -389,6 +458,8 @@
X 				r = 0;
X #ifdef CONFIG_ISDN_AUDIO
X 				isdn_audio_eval_dtmf(info);
+				if ((info->vonline & 1) && (info->emu.vpar[1]))
+					isdn_audio_eval_silence(info);
X #endif
X 				if ((tty = info->tty)) {
X 					if (info->mcr & UART_MCR_RTS) {
@@ -445,6 +516,8 @@
X 	
X 	if (info->vonline)
X 		isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
+	if ((info->vonline & 1) && (info->emu.vpar[1]))
+		isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
X #endif
X 	if ((info->online < 2)
X #ifdef CONFIG_ISDN_AUDIO
@@ -566,8 +639,8 @@
X 					   info->isdn_channel, 1, skb)) == len) {
X 		struct tty_struct *tty = info->tty;
X 		info->send_outstanding++;
-		info->msr |= UART_MSR_CTS;
-		info->lsr |= UART_LSR_TEMT;
+		info->msr &= ~UART_MSR_CTS;
+		info->lsr &= ~UART_LSR_TEMT;
X 		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
X 		    tty->ldisc.write_wakeup)
X 			(tty->ldisc.write_wakeup) (tty);
@@ -579,8 +652,6 @@
X 		dev_kfree_skb(skb);
X 		return;
X 	}
-	if (slen)
-		skb_pull(skb, slen);
X 	skb_queue_head(&info->xmit_queue, skb);
X }
X 
@@ -702,7 +773,6 @@
X 	int audio_len;
X #endif
X 	struct sk_buff *skb;
-	unsigned long flags;
X 
X #ifdef CONFIG_ISDN_AUDIO
X 	if (info->vonline & 4) {
@@ -717,18 +787,20 @@
X 		}
X 	}
X #endif
-	save_flags(flags);
-	cli();
-	if (!(buflen = info->xmit_count)) {
-		restore_flags(flags);
+	if (!(buflen = info->xmit_count))
X 		return;
-	}
-	if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
+ 	if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
X 		info->msr &= ~UART_MSR_CTS;
-	info->lsr &= ~UART_LSR_TEMT;
+	info->lsr &= ~UART_LSR_TEMT;	
+	/* info->xmit_count is modified here and in isdn_tty_write().
+	 * So we return here if isdn_tty_write() is in the
+	 * critical section.
+	 */
+	atomic_inc(&info->xmit_lock);
+	if (!(atomic_dec_and_test(&info->xmit_lock)))
+		return;
X 	if (info->isdn_driver < 0) {
X 		info->xmit_count = 0;
-		restore_flags(flags);
X 		return;
X 	}
X 	skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
@@ -742,7 +814,6 @@
X 	skb = dev_alloc_skb(skb_res + buflen);
X #endif
X 	if (!skb) {
-		restore_flags(flags);
X 		printk(KERN_WARNING
X 		       "isdn_tty: Out of memory in ttyI%d senddown\n",
X 		       info->line);
@@ -751,7 +822,6 @@
X 	skb_reserve(skb, skb_res);
X 	memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
X 	info->xmit_count = 0;
-	restore_flags(flags);
X #ifdef CONFIG_ISDN_AUDIO
X 	if (info->vonline & 2) {
X 		/* For now, ifmt is fixed to 1 (alaw), since this
@@ -859,7 +929,7 @@
X 			break;
X 		}
X #ifdef CONFIG_ISDN_AUDIO
-	if (si == 1) {
+	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
X 		l2 = ISDN_PROTO_L2_TRANS;
X 		usg = ISDN_USAGE_VOICE;
X 	}
@@ -907,9 +977,11 @@
X 		cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
X 		cmd.command = ISDN_CMD_DIAL;
X 		info->dialing = 1;
+		info->emu.carrierwait = 0;
X 		strcpy(dev->num[i], n);
X 		isdn_info_update();
X 		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
X 	}
X }
X 
@@ -942,6 +1014,10 @@
X 		kfree(info->dtmf_state);
X 		info->dtmf_state = NULL;
X 	}
+	if (info->silence_state) {
+		kfree(info->silence_state);
+		info->silence_state = NULL;
+	}
X 	if (info->adpcms) {
X 		kfree(info->adpcms);
X 		info->adpcms = NULL;
@@ -965,8 +1041,9 @@
X 		}
X 		isdn_all_eaz(info->isdn_driver, info->isdn_channel);
X 		info->emu.mdmreg[REG_RINGCNT] = 0;
-		usage = (info->emu.mdmreg[REG_SI1I] == 1) ?
-		    ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
+		usage = ((info->emu.mdmreg[REG_SI1I] != 1) || 
+		    (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
+			ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
X 		isdn_free_channel(info->isdn_driver, info->isdn_channel,
X 				  usage);
X 	}
@@ -978,6 +1055,226 @@
X 	}
X }
X 
+/*
+ * Begin of a CAPI like interface, currently used only for 
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include "avmb1/capicmd.h"  /* this should be moved in a common place */
+
+int
+isdn_tty_capi_facility(capi_msg *cm) {
+	return(-1); /* dummy */
+}
+
+/* isdn_tty_suspend() tries to suspend the current tty connection
+ */
+static void
+isdn_tty_suspend(char *id, modem_info * info, atemu * m)
+{
+	isdn_ctrl cmd;
+	
+	int l;
+
+	if (!info)
+		return;
+
+#ifdef ISDN_DEBUG_MODEM_SERVICES
+	printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
+#endif
+	l = strlen(id);
+	if ((info->isdn_driver >= 0) && l) {
+		cmd.parm.cmsg.Length = l+17;
+		cmd.parm.cmsg.Command = CAPI_FACILITY;
+		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
+		cmd.parm.cmsg.para[1] = 0;
+		cmd.parm.cmsg.para[2] = l + 3;
+		cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
+		cmd.parm.cmsg.para[4] = 0;
+		cmd.parm.cmsg.para[5] = l;
+		strncpy(&cmd.parm.cmsg.para[6], id, l);
+		cmd.command = CAPI_PUT_MESSAGE;
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		isdn_command(&cmd);
+	}
+}
+
+/* isdn_tty_resume() tries to resume a suspended call
+ * setup of the lower levels before that. unfortunatly here is no
+ * checking for compatibility of used protocols implemented by Q931
+ * It does the same things like isdn_tty_dial, the last command
+ * is different, may be we can merge it.
+ */
+
+static void
+isdn_tty_resume(char *id, modem_info * info, atemu * m)
+{
+	int usg = ISDN_USAGE_MODEM;
+	int si = 7;
+	int l2 = m->mdmreg[REG_L2PROT];
+	isdn_ctrl cmd;
+	ulong flags;
+	int i;
+	int j;
+	int l;
+
+	l = strlen(id);
+	if (!l) {
+		isdn_tty_modem_result(4, info);
+		return;
+	}
+	for (j = 7; j >= 0; j--)
+		if (m->mdmreg[REG_SI1] & (1 << j)) {
+			si = bit2si[j];
+			break;
+		}
+#ifdef CONFIG_ISDN_AUDIO
+	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+		l2 = ISDN_PROTO_L2_TRANS;
+		usg = ISDN_USAGE_VOICE;
+	}
+#endif
+	m->mdmreg[REG_SI1I] = si2bit[si];
+	save_flags(flags);
+	cli();
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	if (i < 0) {
+		restore_flags(flags);
+		isdn_tty_modem_result(6, info);
+	} else {
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
+		info->last_dir = 1;
+//		strcpy(info->last_num, n);
+		isdn_info_update();
+		restore_flags(flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
+		info->last_l2 = l2;
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.parm.cmsg.Length = l+17;
+		cmd.parm.cmsg.Command = CAPI_FACILITY;
+		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
+		cmd.parm.cmsg.para[1] = 0;
+		cmd.parm.cmsg.para[2] = l+3;
+		cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
+		cmd.parm.cmsg.para[4] = 0;
+		cmd.parm.cmsg.para[5] = l;
+		strncpy(&cmd.parm.cmsg.para[6], id, l);
+		cmd.command =CAPI_PUT_MESSAGE;
+/*		info->dialing = 1;
+		strcpy(dev->num[i], n);
+		isdn_info_update();
+*/
+		isdn_command(&cmd);
+	}
+}
+
+/* isdn_tty_send_msg() sends a message to a HL driver
+ * This is used for hybrid modem cards to send AT commands to it
+ */
+
+static void
+isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
+{
+	int usg = ISDN_USAGE_MODEM;
+	int si = 7;
+	int l2 = m->mdmreg[REG_L2PROT];
+	isdn_ctrl cmd;
+	ulong flags;
+	int i;
+	int j;
+	int l;
+
+	l = strlen(msg);
+	if (!l) {
+		isdn_tty_modem_result(4, info);
+		return;
+	}
+	for (j = 7; j >= 0; j--)
+		if (m->mdmreg[REG_SI1] & (1 << j)) {
+			si = bit2si[j];
+			break;
+		}
+#ifdef CONFIG_ISDN_AUDIO
+	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+		l2 = ISDN_PROTO_L2_TRANS;
+		usg = ISDN_USAGE_VOICE;
+	}
+#endif
+	m->mdmreg[REG_SI1I] = si2bit[si];
+	save_flags(flags);
+	cli();
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	if (i < 0) {
+		restore_flags(flags);
+		isdn_tty_modem_result(6, info);
+	} else {
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
+		info->last_dir = 1;
+		isdn_info_update();
+		restore_flags(flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
+		info->last_l2 = l2;
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.parm.cmsg.Length = l+14;
+		cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
+		cmd.parm.cmsg.Subcommand = CAPI_REQ;
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 29'
echo 'File patch-2.3.4 is continued in part 30'
echo 30 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 28 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 28; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+					dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+				return 0;
X 			case IIOCSIGPRF:
X 				dev->profd = current;
X 				return 0;
@@ -1543,7 +1610,7 @@
X 					int i;
X 
X 					if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-					(ISDN_MODEM_ANZREG + ISDN_MSNLEN)
+					(ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN)
X 						   * ISDN_MAX_CHANNELS)))
X 						return ret;
X 
@@ -1555,8 +1622,11 @@
X 						if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
X 							return -EFAULT;
X 						p += ISDN_MSNLEN;
+						if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
+							return -EFAULT;
+						p += ISDN_LMSNLEN;
X 					}
-					return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
+					return (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
X 				} else
X 					return -EINVAL;
X 				break;
@@ -1720,7 +1790,6 @@
X 	uint minor = MINOR(ino->i_rdev);
X 	int drvidx;
X 	int chidx;
-	isdn_ctrl c;
X 
X 	if (minor == ISDN_MINOR_STATUS) {
X 		infostruct *p;
@@ -1743,31 +1812,25 @@
X 		if (drvidx < 0)
X 			return -ENODEV;
X 		chidx = isdn_minor2chan(minor);
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
X 			return -ENODEV;
-		if (!(dev->drv[drvidx]->flags & (1 << chidx)))
+		if (!(dev->drv[drvidx]->online & (1 << chidx)))
X 			return -ENODEV;
-		c.command = ISDN_CMD_LOCK;
-		c.driver = drvidx;
-		isdn_command(&c);
-		MOD_INC_USE_COUNT;
+		isdn_MOD_INC_USE_COUNT();
X 		return 0;
X 	}
X 	if (minor <= ISDN_MINOR_CTRLMAX) {
X 		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
X 		if (drvidx < 0)
X 			return -ENODEV;
-		c.command = ISDN_CMD_LOCK;
-		c.driver = drvidx;
-		MOD_INC_USE_COUNT;
-		isdn_command(&c);
+		isdn_MOD_INC_USE_COUNT();
X 		return 0;
X 	}
X #ifdef CONFIG_ISDN_PPP
X 	if (minor <= ISDN_MINOR_PPPMAX) {
X 		int ret;
X 		if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep)))
-			MOD_INC_USE_COUNT;
+			isdn_MOD_INC_USE_COUNT();
X 		return ret;
X 	}
X #endif
@@ -1778,13 +1841,12 @@
X isdn_close(struct inode *ino, struct file *filep)
X {
X 	uint minor = MINOR(ino->i_rdev);
-	int drvidx;
-	isdn_ctrl c;
X 
-	MOD_DEC_USE_COUNT;
X 	if (minor == ISDN_MINOR_STATUS) {
X 		infostruct *p = dev->infochain;
X 		infostruct *q = NULL;
+
+		MOD_DEC_USE_COUNT;
X 		while (p) {
X 			if (p->private == (char *) &(filep->private_data)) {
X 				if (q)
@@ -1800,24 +1862,12 @@
X 		printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
X 		return 0;
X 	}
-	if (minor < ISDN_MINOR_CTRL) {
-		drvidx = isdn_minor2drv(minor);
-		if (drvidx < 0)
-			return 0;
-		c.command = ISDN_CMD_UNLOCK;
-		c.driver = drvidx;
-		isdn_command(&c);
+	isdn_MOD_DEC_USE_COUNT();
+	if (minor < ISDN_MINOR_CTRL)
X 		return 0;
-	}
X 	if (minor <= ISDN_MINOR_CTRLMAX) {
-		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-		if (drvidx < 0)
-			return 0;
X 		if (dev->profd == current)
X 			dev->profd = NULL;
-		c.command = ISDN_CMD_UNLOCK;
-		c.driver = drvidx;
-		isdn_command(&c);
X 		return 0;
X 	}
X #ifdef CONFIG_ISDN_PPP
@@ -1871,7 +1921,6 @@
X 	ulong flags;
X 	ulong features;
X 	ulong vfeatures;
-	isdn_ctrl cmd;
X 
X 	save_flags(flags);
X 	cli();
@@ -1889,7 +1938,7 @@
X 			if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
X 			((pre_dev != d) || (pre_chan != dev->chanmap[i])))
X 				continue;
-			if ((dev->drv[d]->running)) {
+			if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
X 				if (((dev->drv[d]->interface->features & features) == features) ||
X 				    (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
X 				     (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
@@ -1897,10 +1946,6 @@
X 						dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
X 						dev->usage[i] |= usage;
X 						isdn_info_update();
-						cmd.driver = d;
-						cmd.arg = 0;
-						cmd.command = ISDN_CMD_LOCK;
-						isdn_command(&cmd);
X 						restore_flags(flags);
X 						return i;
X 					} else {
@@ -1908,10 +1953,6 @@
X 							dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
X 							dev->usage[i] |= usage;
X 							isdn_info_update();
-							cmd.driver = d;
-							cmd.arg = 0;
-							cmd.command = ISDN_CMD_LOCK;
-							isdn_command(&cmd);
X 							restore_flags(flags);
X 							return i;
X 						}
@@ -1931,7 +1972,6 @@
X {
X 	int i;
X 	ulong flags;
-	isdn_ctrl cmd;
X 
X 	save_flags(flags);
X 	cli();
@@ -1945,12 +1985,6 @@
X 			dev->obytes[i] = 0;
X 			isdn_info_update();
X 			isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
-			cmd.driver = di;
-			cmd.arg = ch;
-			cmd.command = ISDN_CMD_UNLOCK;
-			restore_flags(flags);
-			isdn_command(&cmd);
-			return;
X 		}
X 	restore_flags(flags);
X }
@@ -1995,7 +2029,6 @@
X 		copy_from_user(skb_put(skb, len), buf, len);
X 	else
X 		memcpy(skb_put(skb, len), buf, len);
-
X 	ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
X 	if (ret <= 0)
X 		dev_kfree_skb(skb);
@@ -2051,19 +2084,180 @@
X 	return ret;
X }
X 
+int
+register_isdn_module(isdn_module *m) {
+#if 0
+	isdn_module_list **pp = &dev->modules;
+	isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL);
+
+	if (!new) {
+		printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n");
+		return -1;
+	}
+	while (*pp && (*pp)->orig != m)
+		pp = &(*pp)->next;
+	if (*pp != NULL) {
+		printk(KERN_WARNING "isdn: Module %s already registered\n", m->name);
+		return -1;
+	}
+	while (*pp && ((*pp)->module.priority < m->priority))
+		pp = &(*pp)->next;
+	new->next = *pp;
+	new->orig = m;
+	new->module = *m;
+ 
+	*pp = new;
+#endif
+	return 0;
+}
+
+int
+unregister_isdn_module(isdn_module *m) {
+#if 0
+	isdn_module_list **pp = &dev->modules;
+
+	while (*pp && *pp != m)
+		pp = &(*pp)->next;
+	if (*pp == NULL) {
+		printk(KERN_WARNING "isdn: Module %s not found\n", m->name);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+int
+isdn_add_channels(driver *d, int drvidx, int n, int adding)
+{
+	int j, k, m;
+	ulong flags;
+
+#if LINUX_VERSION_CODE >= 131841
+	init_waitqueue_head(&d->st_waitq);
+#endif
+	if (d->flags & DRV_FLAG_RUNNING)
+		return -1;
+	if (n < 1)
+		return 0;
+
+	m = (adding) ? d->channels + n : n;
+
+	if (dev->channels + n > ISDN_MAX_CHANNELS) {
+		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
+		       ISDN_MAX_CHANNELS);
+		return -1;
+	}
+
+	if ((adding) && (d->rcverr))
+		kfree(d->rcverr);
+	if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
+		return -1;
+	}
+	memset((char *) d->rcverr, 0, sizeof(int) * m);
+
+	if ((adding) && (d->rcvcount))
+		kfree(d->rcvcount);
+	if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
+		if (!adding) kfree(d->rcverr);
+		return -1;
+	}
+	memset((char *) d->rcvcount, 0, sizeof(int) * m);
+
+	if ((adding) && (d->rpqueue)) {
+		for (j = 0; j < d->channels; j++)
+			isdn_free_queue(&d->rpqueue[j]);
+		kfree(d->rpqueue);
+	}
+	if (!(d->rpqueue =
+	      (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
+		if (!adding) {
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1; 
+	}
+	for (j = 0; j < m; j++) {
+		skb_queue_head_init(&d->rpqueue[j]);
+	}
+
+	if ((adding) && (d->rcv_waitq))
+		kfree(d->rcv_waitq);
+#if LINUX_VERSION_CODE < 131841
+	if (!(d->rcv_waitq = (struct wait_queue **)
+	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
+#else
+	d->rcv_waitq = (wait_queue_head_t *)
+		kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
+	if (!d->rcv_waitq) {
+#endif
+		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
+		if (!adding) {
+			kfree(d->rpqueue);
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1;
+	}
+#if LINUX_VERSION_CODE < 131841
+	memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m);
+
+	if ((adding) && (d->snd_waitq))
+		kfree(d->snd_waitq);
+	if (!(d->snd_waitq = (struct wait_queue **)
+	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
+		if (!adding) {
+			kfree(d->rcv_waitq);
+			kfree(d->rpqueue);
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1;
+	}
+	memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m);
+#else
+	d->snd_waitq = d->rcv_waitq + m;
+	for (j = 0; j < m; j++) {
+		init_waitqueue_head(&d->rcv_waitq[m]);
+		init_waitqueue_head(&d->snd_waitq[m]);
+	}
+#endif
+
+	dev->channels += n;
+	save_flags(flags);
+	cli();
+	for (j = d->channels; j < m; j++)
+		for (k = 0; k < ISDN_MAX_CHANNELS; k++)
+			if (dev->chanmap[k] < 0) {
+				dev->chanmap[k] = j;
+				dev->drvmap[k] = drvidx;
+				break;
+			}
+	restore_flags(flags);
+	d->channels = m;
+	return 0;
+}
+
X /*
X  * Low-level-driver registration
X  */
X 
X EXPORT_SYMBOL(register_isdn);
+EXPORT_SYMBOL(register_isdn_module);
+EXPORT_SYMBOL(unregister_isdn_module);
+#ifdef CONFIG_ISDN_PPP
+EXPORT_SYMBOL(isdn_ppp_register_compressor);
+EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
+#endif
X 
X int
X register_isdn(isdn_if * i)
X {
X 	driver *d;
-	int n,
-	 j,
-	 k;
+	int j;
X 	ulong flags;
X 	int drvidx;
X 
@@ -2072,12 +2266,6 @@
X 		       ISDN_MAX_DRIVERS);
X 		return 0;
X 	}
-	n = i->channels;
-	if (dev->channels + n > ISDN_MAX_CHANNELS) {
-		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
-		       ISDN_MAX_CHANNELS);
-		return 0;
-	}
X 	if (!i->writebuf_skb) {
X 		printk(KERN_WARNING "register_isdn: No write routine given.\n");
X 		return 0;
@@ -2087,59 +2275,22 @@
X 		return 0;
X 	}
X 	memset((char *) d, 0, sizeof(driver));
-	init_waitqueue_head(&d->st_waitq); 
-	if (!(d->rcverr = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
-		kfree(d);
-		return 0;
-	}
-	memset((char *) d->rcverr, 0, sizeof(int) * n);
-	if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	memset((char *) d->rcvcount, 0, sizeof(int) * n);
-	if (!(d->rpqueue =
-	      (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
-		kfree(d->rcvcount);
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	for (j = 0; j < n; j++) {
-		skb_queue_head_init(&d->rpqueue[j]);
-	}
-	d->rcv_waitq = (wait_queue_head_t *)
-		kmalloc(sizeof(wait_queue_head_t) * 2 * n, GFP_KERNEL);
-	if (!d->rcv_waitq) { 
-		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
-		kfree(d->rpqueue);
-		kfree(d->rcvcount);
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	d->snd_waitq = d->rcv_waitq + n; 		
-	for (j = 0; j < n; j++) { 
-		init_waitqueue_head(&d->rcv_waitq[n]); 
-		init_waitqueue_head(&d->snd_waitq[n]); 
-	}
-	d->channels = n;
-	d->loaded = 1;
+
X 	d->maxbufsize = i->maxbufsize;
X 	d->pktcount = 0;
X 	d->stavail = 0;
-	d->running = 0;
-	d->flags = 0;
+	d->flags = DRV_FLAG_LOADED;
+	d->online = 0;
X 	d->interface = i;
+	d->channels = 0;
X 	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
X 		if (!dev->drv[drvidx])
X 			break;
+	if (isdn_add_channels(d, drvidx, i->channels, 0)) {
+		kfree(d);
+		return 0;
+	}
X 	i->channels = drvidx;
-
X 	i->rcvcallb_skb = isdn_receive_skb_callback;
X 	i->statcallb = isdn_status_callback;
X 	if (!strlen(i->id))
@@ -2149,15 +2300,7 @@
X 	for (j = 0; j < drvidx; j++)
X 		if (!strcmp(i->id, dev->drvid[j]))
X 			sprintf(i->id, "line%d", drvidx);
-	for (j = 0; j < n; j++)
-		for (k = 0; k < ISDN_MAX_CHANNELS; k++)
-			if (dev->chanmap[k] < 0) {
-				dev->chanmap[k] = j;
-				dev->drvmap[k] = drvidx;
-				break;
-			}
X 	dev->drv[drvidx] = d;
-	dev->channels += n;
X 	strcpy(dev->drvid[drvidx], i->id);
X 	isdn_info_update();
X 	dev->drivers++;
@@ -2209,15 +2352,21 @@
X 	memset((char *) dev, 0, sizeof(isdn_dev));
X 	init_timer(&dev->timer);
X 	dev->timer.function = isdn_timer_funct;
+#if LINUX_VERSION_CODE < 131841
+	dev->sem = MUTEX;
+#else
X 	init_MUTEX(&dev->sem);
-	init_waitqueue_head(&dev->info_waitq); 
+	init_waitqueue_head(&dev->info_waitq);
+#endif
X 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
X 		dev->drvmap[i] = -1;
X 		dev->chanmap[i] = -1;
X 		dev->m_idx[i] = -1;
X 		strcpy(dev->num[i], "???");
+#if LINUX_VERSION_CODE >= 131841
X 		init_waitqueue_head(&dev->mdm.info[i].open_wait);
X 		init_waitqueue_head(&dev->mdm.info[i].close_wait);
+#endif
X 	}
X 	if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
X 		printk(KERN_WARNING "isdn: Could not register control devices\n");
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- v2.3.3/linux/drivers/isdn/isdn_common.h	Fri May 14 18:55:18 1999
+++ linux/drivers/isdn/isdn_common.h	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.h,v 1.9 1998/02/20 17:19:01 fritz Exp $
+/* $Id: isdn_common.h,v 1.15 1999/04/18 14:06:50 fritz Exp $
X 
X  * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fr...@isdn4linux.de)
X * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
X  * Copyright 1995,96    by Michael Hipp (Michae...@student.uni-tuebingen.de)
X  *
@@ -20,11 +20,36 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
X  * $Log: isdn_common.h,v $
+ * Revision 1.15  1999/04/18 14:06:50  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.14 1999/04/12 12:33:18 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.13 1999/03/02 12:04:47 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.12 1998/06/26 15:12:27 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.11 1998/04/14 16:28:47 he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.10 1998/03/07 18:21:03 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
X  * Revision 1.9  1998/02/20 17:19:01  fritz
X  * Added common stub for sending commands to lowlevel.
X  *
@@ -90,10 +115,16 @@
X extern void isdn_timer_ctrl(int tf, int onoff);
X extern void isdn_unexclusive_channel(int di, int ch);
X extern int isdn_getnum(char **);
+#if LINUX_VERSION_CODE < 131841
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
+#else
X extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+#endif
X extern int isdn_get_free_channel(int, int, int, int, int);
X extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
X extern int register_isdn(isdn_if * i);
+extern int isdn_wildmat(char *, char *);
+extern int isdn_add_channels(driver *, int, int, int);
X #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
X extern void isdn_dumppkt(char *, u_char *, int, int);
X #endif
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_concap.c linux/drivers/isdn/isdn_concap.c
--- v2.3.3/linux/drivers/isdn/isdn_concap.c	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_concap.c	Sun May 23 10:03:42 1999
@@ -1,10 +1,21 @@
-/* $Id: isdn_concap.c,v 1.2 1998/01/31 22:49:21 keil Exp $
+/* $Id: isdn_concap.c,v 1.5 1998/10/30 18:44:48 he Exp $
X  
X  * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
X  * stuff goes here. Stuff that depends only on the concap protocol goes to
X  * another -- protocol specific -- source file.
X  *
X  * $Log: isdn_concap.c,v $
+ * Revision 1.5  1998/10/30 18:44:48  he
+ * pass return value from isdn_net_dial_req for dialmode change
+ *
+ * Revision 1.4  1998/10/30 17:55:24  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.3  1998/05/26 22:39:22  he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
X  * Revision 1.2  1998/01/31 22:49:21  keil
X  * correct comments
X  *
@@ -20,14 +31,9 @@
X #include <linux/concap.h>
X #include "isdn_concap.h"
X 
-/* The declaration of this (or a plublic variant thereof) should really go
-   in linux/isdn.h. But we really need it here (and isdn_ppp, like us, also
-   refers to that private function currently owned by isdn_net.c) */
-extern int isdn_net_force_dial_lp(isdn_net_local *);
-
X 
X /* The following set of device service operations are for encapsulation
-   protocols that require for reliable datalink sematics. That means:
+   protocols that require for reliable datalink semantics. That means:
X 
X    - before any data is to be submitted the connection must explicitly
X      be set up.
@@ -66,9 +72,9 @@
X 	IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name);
X 
X 	/* dial ... */
-	ret = isdn_net_force_dial_lp( lp );
+	ret = isdn_net_dial_req( lp );
X 	if ( ret ) IX25DEBUG("dialing failed\n");
-	return 0;
+	return ret;
X }
X 
X int isdn_concap_dl_disconn_req(struct concap_proto *concap)
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.3.3/linux/drivers/isdn/isdn_net.c	Tue Jan 19 11:06:52 1999
+++ linux/drivers/isdn/isdn_net.c	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_net.c,v 1.55 1998/02/23 19:38:22 fritz Exp $
+/* $Id: isdn_net.c,v 1.84 1999/04/18 14:06:55 fritz Exp $
X 
X  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1998  by Fritz Elfert (fr...@isdn4linux.de)
X  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
X  * Copyright 1995,96    by Michael Hipp (Michae...@student.uni-tuebingen.de)
X  *
@@ -20,11 +20,119 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
X  * $Log: isdn_net.c,v $
+ * Revision 1.84  1999/04/18 14:06:55  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.83 1999/04/12 12:33:23 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.82  1999/01/17 00:55:58  he
+ * added mark_bh in BCONN statcallb and cleaned up some dead code
+ *
+ * Revision 1.81  1999/01/15 16:36:52  he
+ * replaced icmp_send() by dst_link_failure()
+ *
+ * Revision 1.80  1998/12/01 13:06:22  paul
+ * Also huptimeout with dialmode == manual
+ *
+ * Revision 1.79  1998/10/30 17:55:27  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.78  1998/10/26 18:20:46  he
+ * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up
+ * on incoming call not matching the first interface)
+ *
+ * Revision 1.77  1998/10/23 10:18:44  paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.76 1998/09/07 22:00:05 he
+ * flush method for 2.1.118 and above
+ * updated IIOCTLNETGPN
+ *
+ * Revision 1.75 1998/08/31 21:09:50 he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
+ * Revision 1.74  1998/07/30 11:28:32  paul
+ * printk message only appeared when status is off and interface is rawIP,
+ * which is confusing for people who don't know about "isdnctrl status <if> on".
+ *
+ * Revision 1.73  1998/06/26 22:01:37  keil
+ * tx_queue_len = 5 was too small
+ *
+ * Revision 1.72  1998/06/26 15:12:31  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.71  1998/06/18 22:43:08  fritz
+ * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at abc-cleanup.
+ *
+ * Revision 1.70  1998/06/17 19:50:49  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.69  1998/06/09 12:27:37  cal
+ * Changed default of local netdev flags: ISDN_NET_STOPPED is default now,
+ * so autodial is suppressed for that device until it is switched on using
+ * 'isdnctrl status dev-name on'.
+ *
+ * Revision 1.68  1998/06/07 00:20:05  fritz
+ * abc cleanup.
+ *
+ * Revision 1.67 1998/06/02 12:10:08 detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.66 1998/05/26 22:39:24 he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.65  1998/05/22 10:01:11  detabc
+ * in case of a icmp-unreach condition the tcp-keepalive-entrys
+ * will be dropped from the internal double-link-list (only abc-extension).
+ * send icmp unreach only if the skb->protocol == ETH_P_IP
+ * speedup abc-no-dchan  redial
+ *
+ * Revision 1.64  1998/05/07 19:58:39  detabc
+ * bugfix in abc_delayed_hangup
+ * optimize keepalive-tests for abc_rawip
+ *
+ * Revision 1.63  1998/05/05 23:23:36  detabc
+ * change ICMP_HOST_UNREACH to ICMP_NET_UNREACH (only abc-ext.)
+ * set dev->tbusy to zero in isdn_net_unreachable() (only abc-ext.)
+ * drop all new packets and send ICMP_NET_UNREACH for
+ * min. dialwait to max. dialwait * 6 time. (only abc-ext.)
+ * change random-deliver of packets (small first) from all emcapsulation
+ * to only rawip with ABC-Router-Flag enabled.
+ *
+ * Revision 1.62  1998/05/03 17:40:42  detabc
+ * Include abc-extension-support for >= 2.1.x Kernels in
+ * isdn_net.c and isdn_common.c. alpha-test OK and running !
+ *
+ * Revision 1.61  1998/04/16 19:19:42  keil
+ * Fix from vger (tx max qlength)
+ *
+ * Revision 1.60  1998/04/14 16:28:49  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.59  1998/03/07 22:37:33  fritz
+ * Bugfix: restore_flags missing.
+ *
+ * Revision 1.58  1998/03/07 18:21:05  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.57  1998/02/25 18:31:13  fritz
+ * Added debugging output in adjust_header.
+ *
+ * Revision 1.56  1998/02/25 17:49:42  he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
X  * Revision 1.55  1998/02/23 19:38:22  fritz
X  * Corrected check for modified feature-flags.
X  *
@@ -248,9 +356,7 @@
X #include <linux/isdn.h>
X #include <net/arp.h>
X #include <net/dst.h>
-#ifndef DEV_NUMBUFFS
X #include <net/pkt_sched.h>
-#endif
X #include <linux/inetdevice.h>
X #include "isdn_common.h"
X #include "isdn_net.h"
@@ -265,14 +371,10 @@
X /* Prototypes */
X 
X int isdn_net_force_dial_lp(isdn_net_local *);
-static int isdn_net_wildmat(char *s, char *p);
X static int isdn_net_start_xmit(struct sk_buff *, struct device *);
X static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
-#ifdef DEV_NUMBUFFS
-static void dev_purge_queues(struct device *dev);	/* move this to net/core/dev.c */
-#endif
X 
-char *isdn_net_revision = "$Revision: 1.55 $";
+char *isdn_net_revision = "$Revision: 1.84 $";
X 
X  /*
X   * Code for raw-networking over ISDN
@@ -293,16 +395,21 @@
X 		
X 		dst_link_failure(skb);
X 	}
+	else {  /* dial not triggered by rawIP packet */
+		printk(KERN_DEBUG "isdn_net: %s: %s\n",
+			   dev->name,
+			   (reason != NULL) ? reason : "reason unknown");
+	}
X }
X 
X static void
X isdn_net_reset(struct device *dev)
X {
X #ifdef CONFIG_ISDN_X25
-	struct concap_device_ops * dops = 
+	struct concap_device_ops * dops =
X 		( (isdn_net_local *) dev->priv ) -> dops;
-	struct concap_proto * cprot = 
-		( (isdn_net_local *) dev->priv ) -> netdev -> cprot; 
+	struct concap_proto * cprot =
+		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
X #endif
X 	ulong flags;
X 
@@ -311,7 +418,7 @@
X 	dev->interrupt = 0;
X 	dev->tbusy = 0;
X #ifdef CONFIG_ISDN_X25
-	if( cprot && cprot -> pops && dops ) 
+	if( cprot && cprot -> pops && dops )
X 		cprot -> pops -> restart ( cprot, dev, dops );
X #endif
X 	restore_flags(flags);
@@ -338,7 +445,7 @@
X 		if (ifa != NULL)
X 			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
X 	}
- 
+
X 	/* If this interface has slaves, start them also */
X 
X 	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
@@ -362,6 +469,7 @@
X 
X 	save_flags(flags);
X 	cli();
+	lp->flags |= ISDN_NET_CONNECTED;
X 	lp->isdn_device = dev->drvmap[idx];
X 	lp->isdn_channel = dev->chanmap[idx];
X 	dev->rx_netdev[idx] = lp->netdev;
@@ -387,10 +495,6 @@
X 		dev_kfree_skb(lp->sav_skb);
X 		lp->sav_skb = NULL;
X 	}
-#ifdef DEV_NUMBUFFS
-	if (!lp->master)        /* purge only for master device */
-		dev_purge_queues(&lp->netdev->dev);
-#else
X 	if (!lp->master) {	/* reset only master device */
X 		/* Moral equivalent of dev_purge_queues():
X 		   BEWARE! This chunk of code cannot be called from hardware
@@ -398,7 +502,6 @@
X 		 */
X 		qdisc_reset(lp->netdev->dev.qdisc);
X 	}
-#endif
X 	lp->dialstate = 0;
X 	dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
X 	dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
@@ -444,7 +547,13 @@
X 		if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
X 			anymore = 1;
X 			l->huptimer++;
-			if ((l->onhtime) && (l->huptimer > l->onhtime)) {
+			/*
+			 * if there is some dialmode where timeout-hangup
+			 * should _not_ be done, check for that here
+			 */
+			if ((l->onhtime) &&
+			    (l->huptimer > l->onhtime))
+			{
X 				if (l->hupflags & ISDN_MANCHARGE &&
X 				    l->hupflags & ISDN_CHARGEHUP) {
X 					while (jiffies - l->chargetime > l->chargeint)
@@ -469,6 +578,11 @@
X 				} else if (l->hupflags & ISDN_INHUP)
X 					isdn_net_hangup(&p->dev);
X 			}
+
+			if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
+				isdn_net_hangup(&p->dev);
+				break;
+			}
X 		}
X 		p = (isdn_net_dev *) p->next;
X 	}
@@ -487,7 +601,7 @@
X {
X 	isdn_net_dev *p = dev->st_netdev[idx];
X 	int cmd = c->command;
-	
+
X 	if (p) {
X 		isdn_net_local *lp = p->local;
X #ifdef CONFIG_ISDN_X25
@@ -538,23 +652,12 @@
X 				   failed. If there are generic encap protocol
X 				   receiver routines signal the closure of
X 				   the link*/
-				
-				if( !(lp->flags & ISDN_NET_CONNECTED) 
+
+				if( !(lp->flags & ISDN_NET_CONNECTED)
X 				    && pops && pops -> disconn_ind )
X 					pops -> disconn_ind(cprot);
X #endif /* CONFIG_ISDN_X25 */
X 				if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
-					lp->flags &= ~ISDN_NET_CONNECTED;
-					if (lp->first_skb) {
-						dev_kfree_skb(lp->first_skb);
-						lp->first_skb = NULL;
-					}
-					if (lp->sav_skb) {
-						dev_kfree_skb(lp->sav_skb);
-						lp->sav_skb = NULL;
-					}
-					isdn_free_channel(lp->isdn_device, lp->isdn_channel,
-							  ISDN_USAGE_NET);
X #ifdef CONFIG_ISDN_PPP
X 					isdn_ppp_free(lp);
X #endif
@@ -562,10 +665,7 @@
X 					printk(KERN_INFO "%s: remote hangup\n", lp->name);
X 					printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
X 					       lp->charge);
-					lp->isdn_device = -1;
-					lp->isdn_channel = -1;
-					dev->st_netdev[idx] = NULL;
-					dev->rx_netdev[idx] = NULL;
+					isdn_net_unbind_channel(lp);
X 					return 1;
X 				}
X 				break;
@@ -607,6 +707,11 @@
X 						lp->chargetime = jiffies;
X 						printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
X 						lp->name, lp->chargetime);
+
+						/* reset dial-timeout */
+						lp->dialstarted = 0;
+						lp->dialwait_timer = 0;
+
X 						/* Immediately send first skb to speed up arp */
X #ifdef CONFIG_ISDN_PPP
X 						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
@@ -617,13 +722,13 @@
X 						if( pops )
X 							if( pops->connect_ind)
X 								pops->connect_ind(cprot);
-
X #endif /* CONFIG_ISDN_X25 */
X 						if (lp->first_skb) {
-							
+
X 							if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
X 								lp->first_skb = NULL;
-						} else {
+						}
+						else {
X 							/*
X 							 * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
X 							 * With an empty lp->first_skb, we need to do this ourselves
@@ -721,6 +826,13 @@
X 					break;
X 				}
X 				anymore = 1;
+
+				if(lp->dialtimeout > 0)
+					if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
+						lp->dialstarted = jiffies;
+						lp->dialwait_timer = 0;
+					}
+
X 				lp->dialstate++;
X 				/* Fall through */
X 			case 2:
@@ -735,12 +847,22 @@
X 				lp->dialretry = 0;
X 				anymore = 1;
X 				lp->dialstate++;
-				/* Falls through */
+				/* Fall through */
X 			case 3:
X 				/* Setup interface, dial current phone-number, switch to next number.
X 				 * If list of phone-numbers is exhausted, increment
X 				 * retry-counter.
X 				 */
+				if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
+					char *s;
+					if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+						s = "dial suppressed: isdn system stopped";
+					else
+						s = "dial suppressed: dialmode `off'";
+					isdn_net_unreachable(&p->dev, lp->first_skb, s);
+					isdn_net_hangup(&p->dev);
+					break;
+				}
X 				cmd.driver = lp->isdn_device;
X 				cmd.command = ISDN_CMD_SETL2;
X 				cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
@@ -765,6 +887,16 @@
X 					lp->dialstate = 4;
X 					printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
X 				} else {
+					if(lp->dialtimeout > 0)
+						if(jiffies > (lp->dialstarted + lp->dialtimeout)) {
+							restore_flags(flags);
+							lp->dialwait_timer = jiffies + lp->dialwait;
+							lp->dialstarted = 0;
+							isdn_net_unreachable(&p->dev, lp->first_skb, "dial: timed out");
+							isdn_net_hangup(&p->dev);
+							break;
+						}
+
X 					sprintf(cmd.parm.setup.phone, "%s", lp->dial->num);
X 					/*
X 					 * Switch to next number or back to start if at end of list.
@@ -772,6 +904,17 @@
X 					if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
X 						lp->dial = lp->phone[1];
X 						lp->dialretry++;
+
+						if (lp->dialretry > lp->dialmax) {
+							restore_flags(flags);
+							if (lp->dialtimeout == 0) {
+								lp->dialwait_timer = jiffies + lp->dialwait;
+								lp->dialstarted = 0;
+								isdn_net_unreachable(&p->dev, lp->first_skb, "dial: tried all numbers dialmax times");
+							}
+							isdn_net_hangup(&p->dev);
+							break;
+						}
X 					}
X 					restore_flags(flags);
X 					cmd.driver = lp->isdn_device;
@@ -786,7 +929,7 @@
X 						isdn_info_update();
X 					}
X 					printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
-					       lp->dialretry - 1, cmd.parm.setup.phone);
+					       lp->dialretry, cmd.parm.setup.phone);
X 					lp->dtimer = 0;
X #ifdef ISDN_DEBUG_NET_DIAL
X 					printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
@@ -810,15 +953,11 @@
X 				break;
X 			case 4:
X 				/* Wait for D-Channel-connect.
-				 * If timeout and max retries not
-				 * reached, switch back to state 3.
+				 * If timeout, switch back to state 3.
+				 * Dialmax-handling moved to state 3.
X 				 */
-				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) {
-					if (lp->dialretry < lp->dialmax) {
-						lp->dialstate = 3;
-					} else
-						isdn_net_hangup(&p->dev);
-				}
+				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					lp->dialstate = 3;
X 				anymore = 1;
X 				break;
X 			case 5:
@@ -895,7 +1034,8 @@
X 				/* Remote does callback. Hangup after cbdelay, then wait for incoming
X 				 * call (in state 4).
X 				 */
-				if (lp->dtimer++ > lp->cbdelay) {
+				if (lp->dtimer++ > lp->cbdelay)
+				{
X 					printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
X 					lp->dtimer = 0;
X 					lp->dialstate = 4;
@@ -930,7 +1070,6 @@
X #endif
X 
X 	if (lp->flags & ISDN_NET_CONNECTED) {
-		lp->flags &= ~ISDN_NET_CONNECTED;
X 		printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
X #ifdef CONFIG_ISDN_PPP
X 		isdn_ppp_free(lp);
@@ -938,7 +1077,7 @@
X #ifdef CONFIG_ISDN_X25
X 		/* try if there are generic encap protocol
X 		   receiver routines and signal the closure of
-		   the link */		
+		   the link */
X 		if( pops && pops -> disconn_ind )
X 		  pops -> disconn_ind(cprot);
X #endif /* CONFIG_ISDN_X25 */
@@ -968,7 +1107,7 @@
X 	char addinfo[100];
X 
X 	addinfo[0] = '\0';
-	/* This check stolen from 2.1.72 dev_queue_xmit_nit() */ 
+	/* This check stolen from 2.1.72 dev_queue_xmit_nit() */
X 	if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) {
X 		/* fall back to old isdn_net_log_packet method() */
X 		char * buf = skb->data;
@@ -1062,20 +1201,17 @@
X 	if (ret == len) {
X 		lp->transcount += len;
X 		clear_bit(0, (void *) &(ndev->tbusy));
-		mark_bh(NET_BH);
X 		return 0;
X 	}
X 	if (ret < 0) {
X 		dev_kfree_skb(skb);
X 		lp->stats.tx_errors++;
X 		clear_bit(0, (void *) &(ndev->tbusy));
-		mark_bh(NET_BH);
X 		return 0;
X 	}
X 	return 1;
X }
X 
-
X /*
X  *  Helper function for isdn_net_start_xmit.
X  *  When called, the connection is already established.
@@ -1150,9 +1286,11 @@
X 	if (!skb)
X 		return;
X 	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
-		ulong pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
-		if (pullsize)
+		int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
+		if (pullsize > 0) {
+			printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
X 			skb_pull(skb, pullsize);
+		}
X 	}
X }
X 
@@ -1166,7 +1304,7 @@
X {
X 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
X #ifdef CONFIG_ISDN_X25
-	struct concap_proto * cprot = lp -> netdev -> cprot; 
+	struct concap_proto * cprot = lp -> netdev -> cprot;
X #endif
X 
X 	if (ndev->tbusy) {
@@ -1179,7 +1317,7 @@
X 	ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
X #ifdef CONFIG_ISDN_X25
X /* At this point hard_start_xmit() passes control to the encapsulation
-   protocol (if present). 
+   protocol (if present).
X    For X.25 auto-dialing is completly bypassed because:
X    - It does not conform with the semantics of a reliable datalink
X      service as needed by X.25 PLP.
@@ -1205,17 +1343,46 @@
X #endif
X 		if (!(lp->flags & ISDN_NET_CONNECTED)) {
X 			int chi;
+			/* only do autodial if allowed by config */
+			if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
+				isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
+				dev_kfree_skb(skb);
+				ndev->tbusy = 0;
+				return 0;
+			}
X 			if (lp->phone[1]) {
X 				ulong flags;
X 				save_flags(flags);
X 				cli();
+
+				if(lp->dialwait_timer <= 0)
+					if(lp->dialstarted > 0 && lp->dialtimeout > 0 && jiffies < lp->dialstarted + lp->dialtimeout + lp->dialwait)
+						lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
+
+				if(lp->dialwait_timer > 0) {
+					if(jiffies < lp->dialwait_timer) {
+						isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
+						dev_kfree_skb(skb);
+						ndev->tbusy = 0;
+						restore_flags(flags);
+						return 0;
+					} else
+						lp->dialwait_timer = 0;
+				}
+
X 				/* Grab a free ISDN-Channel */
-				if ((chi =
+				if (((chi =
X 				     isdn_get_free_channel(ISDN_USAGE_NET,
X 							   lp->l2_proto,
X 							   lp->l3_proto,
X 							   lp->pre_device,
-						 lp->pre_channel)) < 0) {
+						 lp->pre_channel)) < 0) &&
+					((chi =
+				     isdn_get_free_channel(ISDN_USAGE_NET,
+							   lp->l2_proto,
+							   lp->l3_proto,
+							   lp->pre_device,
+						 lp->pre_channel^1)) < 0)) {
X 					restore_flags(flags);
X 					isdn_net_unreachable(ndev, skb,
X 							   "No channel");
@@ -1227,7 +1394,6 @@
X 				if (dev->net_verbose)
X 					isdn_net_log_skb(skb, lp);
X 				lp->dialstate = 1;
-				lp->flags |= ISDN_NET_CONNECTED;
X 				/* Connect interface with channel */
X 				isdn_net_bind_channel(lp, chi);
X #ifdef CONFIG_ISDN_PPP
@@ -1290,8 +1456,8 @@
X {
X 	struct device *p;
X #ifdef CONFIG_ISDN_X25
-	struct concap_proto * cprot = 
-		( (isdn_net_local *) dev->priv ) -> netdev -> cprot; 
+	struct concap_proto * cprot =
+		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
X 	/* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
X #endif
X 
@@ -1304,9 +1470,9 @@
X 		/* If this interface has slaves, stop them also */
X 		while (p) {
X #ifdef CONFIG_ISDN_X25
-			cprot = ( (isdn_net_local *) p->priv ) 
-				-> netdev -> cprot; 
-			if( cprot && cprot -> pops ) 
+			cprot = ( (isdn_net_local *) p->priv )
+				-> netdev -> cprot;
+			if( cprot && cprot -> pops )
X 				cprot -> pops -> close( cprot );
X #endif
X 			isdn_net_hangup(p);
@@ -1392,7 +1558,7 @@
X 	int len;
X 	cisco_hdr *ch;
X 	cisco_slarp *s;
-	
+
X 	if (!skb) {
X 		printk(KERN_WARNING
X 		       "%s: Could not allocate SLARP reply\n", lp->name);
@@ -1406,7 +1572,7 @@
X 	s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp));
X 	if (is_reply) {
X 		s->code = htonl(CISCO_SLARP_REPLY);
- 		memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
+		memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
X 		memset(&s->slarp.reply.netmask, 0, sizeof(__u32));
X 	} else {
X 		lp->cisco_myseq++;
@@ -1589,7 +1755,7 @@
X 		default:
X #ifdef CONFIG_ISDN_X25
X 		  /* try if there are generic sync_device receiver routines */
-			if(cprot) if(cprot -> pops) 
+			if(cprot) if(cprot -> pops)
X 				if( cprot -> pops -> data_ind){
X 					cprot -> pops -> data_ind(cprot,skb);
X 					return;
@@ -1600,6 +1766,7 @@
X 			kfree_skb(skb);
X 			return;
X 	}
+
X 	netif_rx(skb);
X 	return;
X }
@@ -1788,16 +1955,12 @@
X 	ndev->type = ARPHRD_ETHER;
X 	ndev->addr_len = ETH_ALEN;
X 
-	ndev->tx_queue_len = 10; /* for clients without MPPP 5 is better.  */
+	/* for clients with MPPP maybe higher values better */
+	ndev->tx_queue_len = 30;
X 
X 	for (i = 0; i < ETH_ALEN; i++)
X 		ndev->broadcast[i] = 0xff;
X 
-#ifdef DEV_NUMBUFFS
-	for (i = 0; i < DEV_NUMBUFFS; i++)
-		skb_queue_head_init(&ndev->buffs[i]);
-#endif
-
X 	/* The ISDN-specific entries in the device structure. */
X 	ndev->open = &isdn_net_open;
X 	ndev->hard_start_xmit = &isdn_net_start_xmit;
@@ -1813,86 +1976,15 @@
X 				max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
X 
X 	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
-
X 	ndev->stop = &isdn_net_close;
X 	ndev->get_stats = &isdn_net_get_stats;
X 	ndev->rebuild_header = &isdn_net_rebuild_header;
-
X #ifdef CONFIG_ISDN_PPP
X 	ndev->do_ioctl = isdn_ppp_dev_ioctl;
X #endif
X 	return 0;
X }
X 
-/*
- * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
- * It was originally written and put to PD by r...@mirror.TMC.COM (Rich Salz)
- */
-
-static int
-isdn_net_Star(char *s, char *p)
-{
-	while (isdn_net_wildmat(s, p) == 0)
-		if (*++s == '\0')
-			return (0);
-	return (1);
-}
-
-/*
- * Shell-type Pattern-matching for incoming caller-Ids
- * This function gets a string in s and checks, if it matches the pattern
- * given in p. It returns 1 on success, 0 otherwise.
- *
- * Possible Patterns:
- *
- * '?'     matches one character
- * '*'     matches zero or more characters
- * [xyz]   matches the set of characters in brackets.
- * [^xyz]  matches any single character not in the set of characters
- */
-
-static int
-isdn_net_wildmat(char *s, char *p)
-{
-	register int last;
-	register int matched;
-	register int reverse;
-
-	for (; *p; s++, p++)
-		switch (*p) {
-			case '\\':
-				/*
-				 * Literal match with following character,
-				 * fall through.
-				 */
-				p++;
-			default:
-				if (*s != *p)
-					return (0);
-				continue;
-			case '?':
-				/* Match anything. */
-				if (*s == '\0')
-					return (0);
-				continue;
-			case '*':
-				/* Trailing star matches everything. */
-				return (*++p ? isdn_net_Star(s, p) : 1);
-			case '[':
-				/* [^....] means inverse character class. */
-				if ((reverse = (p[1] == '^')))
-					p++;
-				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
-					/* This next line requires a good C compiler. */
-					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
-						matched = 1;
-				if (matched == reverse)
-					return (0);
-				continue;
-		}
-	return (*s == '\0');
-}
-
X static void
X isdn_net_swapbind(int drvidx)
X {
@@ -1945,6 +2037,8 @@
X  *               2 = Reject call, wait cbdelay, then call back
X  *               3 = Reject call
X  *               4 = Wait cbdelay, then call back
+ *               5 = No appropriate interface for this call,
+ *                   would eventually match if CID was longer.
X  */
X int
X isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
@@ -1953,6 +2047,7 @@
X 	int si1;
X 	int si2;
X 	int ematch;
+	int wret;
X 	int swapped;
X 	int sidx = 0;
X 	isdn_net_dev *p;
@@ -1987,13 +2082,13 @@
X 	}
X 	n = (isdn_net_phone *) 0;
X 	p = dev->netdev;
-	ematch = 0;
+	ematch = wret = swapped = 0;
X #ifdef ISDN_DEBUG_NET_ICALL
X 	printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
X 	       dev->usage[idx]);
X #endif
-	swapped = 0;
X 	while (p) {
+		int matchret;
X 		isdn_net_local *lp = p->local;
X 
X 		/* If last check has triggered as binding-swap, revert it */
@@ -2006,18 +2101,22 @@
X 				break;
X 		}
X 		swapped = 0;
-		if (!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz))
+		if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di))))
X 			ematch = 1;
+		/* Remember if more numbers eventually can match */
+		if (matchret > wret)
+			wret = matchret;
X #ifdef ISDN_DEBUG_NET_ICALL
X 		printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
X 		       lp->name, lp->msn, lp->flags, lp->dialstate);
X #endif
-		if ((!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz)) &&	/* EAZ is matching   */
-		    (((!(lp->flags & ISDN_NET_CONNECTED)) &&	/* but not connected */
-		      (USG_NONE(dev->usage[idx]))) ||	/* and ch. unused or */
-		     ((((lp->dialstate == 4) || (lp->dialstate == 12)) &&	/* if dialing        */
-		       (!(lp->flags & ISDN_NET_CALLBACK)))	/* but no callback   */
-		     ))) {
+		if ((!matchret) &&                                        /* EAZ is matching   */
+		    (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */
+		      (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */
+		     ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing        */
+		       (!(lp->flags & ISDN_NET_CALLBACK)))                /* but no callback   */
+		     )))
+			 {
X #ifdef ISDN_DEBUG_NET_ICALL
X 			printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
X 			       lp->pre_device, lp->pre_channel);
@@ -2085,8 +2184,6 @@
X #ifdef ISDN_DEBUG_NET_ICALL
X 						printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
X #endif
-						p = (isdn_net_dev *) p->next;
-						continue;
X 					}
X 				}
X 			}
@@ -2096,7 +2193,7 @@
X 			n = lp->phone[0];
X 			if (lp->flags & ISDN_NET_SECURE) {
X 				while (n) {
-					if (isdn_net_wildmat(nr, n->num))
+					if (!isdn_wildmat(nr, n->num))
X 						break;
X 					n = (isdn_net_phone *) n->next;
X 				}
@@ -2105,7 +2202,21 @@
X #ifdef ISDN_DEBUG_NET_ICALL
X 				printk(KERN_DEBUG "n_fi: match3\n");
X #endif
-				/* Here we got an interface matched, now see if it is up.
+				/* matching interface found */
+
+				/*
+				 * Is the state STOPPED?
+				 * If so, no dialin is allowed,
+				 * so reject actively.
+				 * */
+				if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+					restore_flags(flags);
+					printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
+					       lp->name);
+					return 3;
+				}
+				/*
+				 * Is the interface up?
X 				 * If not, reject the call actively.
X 				 */
X 				if (!p->dev.start) {
@@ -2140,6 +2251,17 @@
X 				}
X 				if (lp->flags & ISDN_NET_CALLBACK) {
X 					int chi;
+					/*
+					 * Is the state MANUAL?
+					 * If so, no callback can be made,
+					 * so reject actively.
+					 * */
+					if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+						restore_flags(flags);
+						printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
+						       lp->name);
+						return 3;
+					}
X 					printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
X 					       lp->name, nr, eaz);
X 					if (lp->phone[1]) {
@@ -2155,7 +2277,6 @@
X 						/* Setup dialstate. */
X 						lp->dtimer = 0;
X 						lp->dialstate = 11;
-						lp->flags |= ISDN_NET_CONNECTED;
X 						/* Connect interface with channel */
X 						isdn_net_bind_channel(lp, chi);
X #ifdef CONFIG_ISDN_PPP
@@ -2217,10 +2338,10 @@
X 		p = (isdn_net_dev *) p->next;
X 	}
X 	/* If none of configured EAZ/MSN matched and not verbose, be silent */
-	if (ematch || dev->net_verbose)
+	if (!ematch || dev->net_verbose)
X 		printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
X 	restore_flags(flags);
-	return 0;
+	return (wret == 2)?5:0;
X }
X 
X /*
@@ -2253,6 +2374,7 @@
X 			ulong flags;
X 			save_flags(flags);
X 			cli();
+
X 			/* Grab a free ISDN-Channel */
X 			if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
X 							 lp->l3_proto,
@@ -2263,7 +2385,6 @@
X 				return -EAGAIN;
X 			}
X 			lp->dialstate = 1;
-			lp->flags |= ISDN_NET_CONNECTED;
X 			/* Connect interface with channel */
X 			isdn_net_bind_channel(lp, chi);
X #ifdef CONFIG_ISDN_PPP
@@ -2285,6 +2406,20 @@
X }
X 
X /*
+ * This is called from certain upper protocol layers (multilink ppp
+ * and x25iface encapsulation module) that want to initiate dialing
+ * themselves.
+ */
+int
+isdn_net_dial_req(isdn_net_local * lp)
+{
+	/* is there a better error code? */
+	if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
+
+	return isdn_net_force_dial_lp(lp);
+}
+
+/*
X  * Force a net-interface to dial out.
X  * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
X  */
@@ -2383,8 +2518,13 @@
X 	netdev->local->onhtime = 10;	/* Default hangup-time for saving costs
X 	   of those who forget configuring this */
X 	netdev->local->dialmax = 1;
-	netdev->local->flags = ISDN_NET_CBHUP;	/* Hangup before Callback */
+	netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;	/* Hangup before Callback, manual dial */
X 	netdev->local->cbdelay = 25;	/* Wait 5 secs before Callback */
+	netdev->local->dialtimeout = -1;  /* Infinite Dial-Timeout */
+	netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
+	netdev->local->dialstarted = 0;   /* Jiffies of last dial-start */
+	netdev->local->dialwait_timer = 0;  /* Jiffies of earliest next dial-start */
+
X 	/* Put into to netdev-chain */
X 	netdev->next = (void *) dev->netdev;
X 	dev->netdev = netdev;
@@ -2465,7 +2605,7 @@
X 			save_flags(flags);
X 			cli(); /* avoid races with incoming events trying to
X 				  call cprot->pops methods */
-			if( cprot && cprot -> pops ) 
+			if( cprot && cprot -> pops )
X 				cprot -> pops -> proto_del ( cprot );
X 			p -> cprot = NULL;
X 			lp -> dops = NULL;
@@ -2479,7 +2619,7 @@
X 			p -> cprot = isdn_concap_new( cfg -> p_encap );
X 			/* p -> cprot == NULL now if p_encap is not supported
X 			   by means of the concap_proto mechanism */
-			/* the protocol is not configured yet; this will 
+			/* the protocol is not configured yet; this will
X 			   happen later when isdn_net_reset() is called */
X #endif
X 		}
@@ -2508,7 +2648,7 @@
X 			if( cfg->p_encap >= 0 &&
X 			    cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
X 				break;
-			printk(KERN_WARNING 
+			printk(KERN_WARNING
X 			       "%s: encapsulation protocol %d not supported\n",
X 			       p->local->name, cfg->p_encap);
X 			return -EINVAL;
@@ -2583,6 +2723,8 @@
X 		lp->triggercps = cfg->triggercps;
X 		lp->slavedelay = cfg->slavedelay * HZ;
X 		lp->pppbind = cfg->pppbind;
+		lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
+		lp->dialwait = cfg->dialwait * HZ;
X 		if (cfg->secure)
X 			lp->flags |= ISDN_NET_SECURE;
X 		else
@@ -2604,6 +2746,16 @@
X 				lp->flags &= ~ISDN_NET_CALLBACK;
X 				break;
X 		}
+		lp->flags &= ~ISDN_NET_DIALMODE_MASK;	/* first all bits off */
+		if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
+			/* old isdnctrl version, where only 0 or 1 is given */
+			printk(KERN_WARNING
+			     "Old isdnctrl version detected! Please update.\n");
+			lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
+		}
+		else {
+			lp->flags |= cfg->dialmode;  /* turn on selected bits */
+		}
X 		if (cfg->chargehup)
X 			lp->hupflags |= ISDN_CHARGEHUP;
X 		else
@@ -2671,6 +2823,7 @@
X 		if (lp->flags & ISDN_NET_CBOUT)
X 			cfg->callback = 2;
X 		cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
+		cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
X 		cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
X 		cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
X 		cfg->cbdelay = lp->cbdelay;
@@ -2680,6 +2833,8 @@
X 		cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
X 		    (lp->chargeint / HZ) : 0;
X 		cfg->pppbind = lp->pppbind;
+		cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
+		cfg->dialwait = lp->dialwait / HZ;
X 		if (lp->slave)
X 			strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
X 		else
@@ -2749,9 +2904,37 @@
X }
X 
X /*
- * Delete a phone-number from an interface.
+ * Copy a string containing the peer's phone number of a connected interface
+ * to user space.
X  */
+int
+isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
+{
+	isdn_net_dev *p = isdn_net_findif(phone->name);
+	int ch, dv, idx;
X 
+	if (!p) return -ENODEV;
+	/*
+	 * Theoretical race: while this executes, the remote number might
+	 * become invalid (hang up) or change (new connection), resulting
+         * in (partially) wrong number copied to user. This race
+	 * currently ignored.
+	 */
+	ch = p->local->isdn_channel;
+	dv = p->local->isdn_device;
+	if(ch<0 && dv<0) return -ENOTCONN;
+	idx = isdn_dc2minor(dv, ch);
+	if (idx<0) return -ENODEV;
+	/* for pre-bound channels, we need this extra check */
+	if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
+	strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
+	phone->outgoing=USG_OUTGOING(idx);
+	if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
+	return 0;
+}
+/*
+ * Delete a phone-number from an interface.
+ */
X int
X isdn_net_delphone(isdn_net_ioctl_phone * phone)
X {
@@ -2957,21 +3140,3 @@
X 	restore_flags(flags);
X 	return 0;
X }
-
-#ifdef DEV_NUMBUFFS
-/*
- * helper function to flush device queues
- * the better place would be net/core/dev.c
- */
-static void
-dev_purge_queues(struct device *dev)
-{
-	int i;
-	for (i = 0; i < DEV_NUMBUFFS; i++) {
-		struct sk_buff *skb;
-		while ((skb = skb_dequeue(&dev->buffs[i])))
-			dev_kfree_skb(skb);
-	}
-
-}
-#endif
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h
--- v2.3.3/linux/drivers/isdn/isdn_net.h	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_net.h	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_net.h,v 1.6 1997/10/09 21:28:54 fritz Exp $
+/* $Id: isdn_net.h,v 1.9 1999/04/12 12:33:27 fritz Exp $
X 
X  * header for Linux ISDN subsystem, network related functions (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fr...@isdn4linux.de)
X * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
X  * Copyright 1995,96    by Michael Hipp (Michae...@student.uni-tuebingen.de)
X  *
@@ -21,6 +21,16 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_net.h,v $
+ * Revision 1.9  1999/04/12 12:33:27  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.8  1998/10/30 17:55:33  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.7  1998/08/31 21:09:55  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
X * Revision 1.6 1997/10/09 21:28:54 fritz
X  * New HL<->LL interface:
X  *   New BSENT callback with nr. of bytes included.
@@ -99,6 +109,7 @@
X extern int isdn_net_getcfg(isdn_net_ioctl_cfg *);
X extern int isdn_net_addphone(isdn_net_ioctl_phone *);
X extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *);
+extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
X extern int isdn_net_delphone(isdn_net_ioctl_phone *);
X extern int isdn_net_find_icall(int, int, int, setup_parm);
X extern void isdn_net_hangup(struct device *);
@@ -111,3 +122,4 @@
X 			     struct sk_buff *);
X extern int isdn_net_rcv_skb(int, struct sk_buff *);
X extern void isdn_net_slarp_out(void);
+extern int isdn_net_dial_req(isdn_net_local *);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.3.3/linux/drivers/isdn/isdn_ppp.c	Fri May 14 18:55:18 1999
+++ linux/drivers/isdn/isdn_ppp.c	Sun May 23 10:03:42 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.33 1998/02/20 17:11:54 fritz Exp $
+/* $Id: isdn_ppp.c,v 1.47 1999/04/18 14:06:59 fritz Exp $
X  *
X  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
X  *
@@ -18,11 +18,50 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
X  * $Log: isdn_ppp.c,v $
+ * Revision 1.47  1999/04/18 14:06:59  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.46 1999/04/12 12:33:35 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.45  1998/12/30 17:48:24  paul
+ * fixed syncPPP callback out
+ *
+ * Revision 1.44  1998/10/30 17:55:34  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.43  1998/10/29 17:23:54  hipp
+ * Minor MPPP fixes, verboser logging.
+ *
+ * Revision 1.42  1998/07/20 11:30:07  hipp
+ * Readded compression check
+ *
+ * Revision 1.41  1998/07/08 16:50:57  hipp
+ * Compression changes
+ *
+ * Revision 1.40  1998/04/06 19:07:27  hipp
+ * added check, whether compression is enabled.
+ *
+ * Revision 1.39  1998/03/25 22:46:53  hipp
+ * Some additional CCP changes.
+ *
+ * Revision 1.38  1998/03/24 16:33:06  hipp
+ * More CCP changes. BSD compression now "works" on a local loopback link.
+ * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
+ *
+ * Revision 1.37  1998/03/22 18:50:49  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.36 1998/03/09 17:46:30 he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.35 1998/03/07 18:21:11 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.34 1998/02/25 17:49:48 he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
X * Revision 1.33 1998/02/20 17:11:54 fritz
X  * Changes for recent kernels.
X  *
@@ -157,13 +196,16 @@
X  * experimental for dynamic addressing: readdress IP frames
X  */
X #undef ISDN_SYNCPPP_READDRESS
+#define CONFIG_ISDN_CCP 1
X 
X #include <linux/config.h>
X #define __NO_VERSION__
X #include <linux/module.h>
X #include <linux/version.h>
-#include <linux/isdn.h>
X #include <linux/poll.h>
+#include <linux/isdn.h>
+#include <linux/ppp-comp.h>
+
X #include "isdn_common.h"
X #include "isdn_ppp.h"
X #include "isdn_net.h"
@@ -180,13 +222,33 @@
X static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
X 				 struct sk_buff *skb, int proto);
X static int isdn_ppp_if_get_unit(char *namebuf);
-static int isdn_ppp_set_compressor(struct ippp_struct *is,int num);
+static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
X static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
-				struct ippp_struct *,struct ippp_struct *);
+				struct ippp_struct *,struct ippp_struct *,int proto);
X static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
-				struct sk_buff *skb);
+				struct sk_buff *skb,int proto);
X static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
X struct ippp_struct *is,struct ippp_struct *master,int type);
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+	 struct sk_buff *skb);
+
+/* New CCP stuff */
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+				    unsigned char code, unsigned char id,
+				    unsigned char *data, int len);
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+					  unsigned char id);
+static void isdn_ppp_ccp_timer_callback(unsigned long closure);
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+ unsigned char id);
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+ struct isdn_ppp_resetparams *rp);
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+					unsigned char id);
+
+
X 
X #ifdef CONFIG_ISDN_MPP
X static int isdn_ppp_bundle(struct ippp_struct *, int unit);
@@ -199,18 +261,16 @@
X static void isdn_ppp_free_mpqueue(isdn_net_dev *);
X #endif
X 
-char *isdn_ppp_revision = "$Revision: 1.33 $";
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 28'
echo 'File patch-2.3.4 is continued in part 29'
echo 29 > _shar_seq_.tmp
#!/bin/sh
# this is part 30 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 30; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+		cmd.parm.cmsg.para[0] = l+1;
+		strncpy(&cmd.parm.cmsg.para[1], msg, l);
+		cmd.parm.cmsg.para[l+1] = 0xd;
+		cmd.command =CAPI_PUT_MESSAGE;
+/*		info->dialing = 1;
+		strcpy(dev->num[i], n);
+		isdn_info_update();
+*/
+		isdn_command(&cmd);
+	}
+}
+
X static inline int
X isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
X {
@@ -1138,15 +1435,16 @@
X {
X 	int c;
X 	int total = 0;
-	ulong flags;
X 	modem_info *info = (modem_info *) tty->driver_data;
X 
X 	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
X 		return 0;
X 	if (!tty)
X 		return 0;
-	save_flags(flags);
-	cli();
+	if (from_user)
+		down(&info->write_sem);
+	/* See isdn_tty_senddown() */
+	atomic_inc(&info->xmit_lock);
X 	while (1) {
X 		c = MIN(count, info->xmit_size - info->xmit_count);
X 		if (info->isdn_driver >= 0)
@@ -1205,10 +1503,6 @@
X 			} else
X #endif
X 				info->xmit_count += c;
-			if (m->mdmreg[REG_DELXMT] & BIT_DELXMT) {
-				isdn_tty_senddown(info);
-				isdn_tty_tint(info);
-			}
X 		} else {
X 			info->msr |= UART_MSR_CTS;
X 			info->lsr |= UART_LSR_TEMT;
@@ -1228,7 +1522,9 @@
X 	}
X 	if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
X 		isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
-	restore_flags(flags);
+	atomic_dec(&info->xmit_lock);
+	if (from_user)
+		up(&info->write_sem);
X 	return total;
X }
X 
@@ -1359,7 +1655,7 @@
X 	status = info->lsr;
X 	restore_flags(flags);
X 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	put_user(result, (ulong *) value);
+	put_user(result, (uint *) value);
X 	return 0;
X }
X 
@@ -1383,7 +1679,7 @@
X 	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
X 	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
X 	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	put_user(result, (ulong *) value);
+	put_user(result, (uint *) value);
X 	return 0;
X }
X 
@@ -1567,7 +1863,12 @@
X static int
X isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
X {
-	DECLARE_WAITQUEUE(wait, current); 
+#if LINUX_VERSION_CODE < 131841
+	struct wait_queue wait =
+	{current, NULL};
+#else
+	DECLARE_WAITQUEUE(wait, NULL);
+#endif
X 	int do_clocal = 0;
X 	unsigned long flags;
X 	int retval;
@@ -1891,6 +2192,7 @@
X 	m->profile[19] = 0;
X 	m->profile[20] = 0;
X 	m->pmsn[0] = '\0';
+	m->plmsn[0] = '\0';
X }
X 
X #ifdef CONFIG_ISDN_AUDIO
@@ -1911,6 +2213,7 @@
X 	if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
X 		memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
X 		memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
+		memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
X 		info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
X 	}
X #ifdef CONFIG_ISDN_AUDIO
@@ -1924,6 +2227,7 @@
X {
X 	memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
X 	memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
+	memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
X 	if (dev->profd)
X 		send_sig(SIGIO, dev->profd, 1);
X }
@@ -1987,6 +2291,11 @@
X 	}
X 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
X 		info = &m->info[i];
+#if LINUX_VERSION_CODE < 131841
+		info->write_sem = MUTEX;
+#else
+		init_MUTEX(&info->write_sem);
+#endif
X 		sprintf(info->last_cause, "0000");
X 		sprintf(info->last_num, "none");
X 		info->last_dir = 0;
@@ -2003,8 +2312,13 @@
X 		info->blocked_open = 0;
X 		info->callout_termios = m->cua_modem.init_termios;
X 		info->normal_termios = m->tty_modem.init_termios;
+#if LINUX_VERSION_CODE < 131841
+		info->open_wait = 0;
+		info->close_wait = 0;
+#else
X 		init_waitqueue_head(&info->open_wait);
X 		init_waitqueue_head(&info->close_wait);
+#endif
X 		info->isdn_driver = -1;
X 		info->isdn_channel = -1;
X 		info->drv_index = -1;
@@ -2023,25 +2337,67 @@
X 	return 0;
X }
X 
+static int
+isdn_tty_match_icall(char *cid, atemu *emu, int di)
+{
+#ifdef ISDN_DEBUG_MODEM_ICALL
+	printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
+	       emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
+	       emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
+#endif
+	if (strlen(emu->lmsn)) {
+		char *p = emu->lmsn;
+		char *q;
+		int  tmp;
+		int  ret = 0;
+
+		while (1) {
+			if ((q = strchr(p, ';')))
+				*q = '\0';
+			if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret)
+				ret = tmp;
+#ifdef ISDN_DEBUG_MODEM_ICALL
+			printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
+			       p, isdn_map_eaz2msn(emu->msn, di), tmp);
+#endif
+			if (q) {
+				*q = ';';
+				p = q;
+				p++;
+			}
+			if (!tmp)
+				return 0;
+			if (!q)
+				break;
+		}
+		return ret;
+	} else
+		return isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+}
+
X /*
X  * An incoming call-request has arrived.
X  * Search the tty-devices for an appropriate device and bind
X  * it to the ISDN-Channel.
- * Return Index to dev->mdm or -1 if none found.
+ * Return:
+ *
+ *  0 = No matching device found.
+ *  1 = A matching device found.
+ *  3 = No match found, but eventually would match, if
+ *      CID is longer.
X  */
X int
X isdn_tty_find_icall(int di, int ch, setup_parm setup)
X {
X 	char *eaz;
X 	int i;
+	int wret;
X 	int idx;
X 	int si1;
X 	int si2;
X 	char nr[32];
X 	ulong flags;
X 
-	save_flags(flags);
-	cli();
X 	if (!setup.phone[0]) {
X 		nr[0] = '0';
X 		nr[1] = '\0';
@@ -2058,17 +2414,14 @@
X #ifdef ISDN_DEBUG_MODEM_ICALL
X 	printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
X #endif
+	wret = 0;
+	save_flags(flags);
+	cli();
X 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
X 		modem_info *info = &dev->mdm.info[i];
-#ifdef ISDN_DEBUG_MODEM_ICALL
-		printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
-		       info->emu.msn, isdn_map_eaz2msn(info->emu.msn, di),
-		       info->emu.mdmreg[REG_SI1], info->emu.mdmreg[REG_SI2]);
-#endif
-		if ((!strcmp(isdn_map_eaz2msn(info->emu.msn, di),
-			     eaz)) &&	                          /* EAZ is matching */
-		    (info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
-		    (info->emu.mdmreg[REG_SI2] == si2)) {	  /* SI2 is matching */
+
+		if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
+		    (info->emu.mdmreg[REG_SI2] == si2))	{         /* SI2 is matching */
X 			idx = isdn_dc2minor(di, ch);
X #ifdef ISDN_DEBUG_MODEM_ICALL
X 			printk(KERN_DEBUG "m_fi: match1\n");
@@ -2080,34 +2433,42 @@
X #ifndef FIX_FILE_TRANSFER
X 				(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
X #endif
-			    (info->isdn_driver == -1) &&
-			    (info->isdn_channel == -1) &&
-			    (USG_NONE(dev->usage[idx]))) {
-				info->isdn_driver = di;
-				info->isdn_channel = ch;
-				info->drv_index = idx;
-				dev->m_idx[idx] = info->line;
-				dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
-				dev->usage[idx] |= (si1 == 1) ? ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
-				strcpy(dev->num[idx], nr);
-				info->emu.mdmreg[REG_SI1I] = si2bit[si1];
-				info->emu.mdmreg[REG_PLAN] = setup.plan;
-				info->emu.mdmreg[REG_SCREEN] = setup.screen;
-				isdn_info_update();
-				restore_flags(flags);
-				printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
-				       info->line);
-				info->msr |= UART_MSR_RI;
-				isdn_tty_modem_result(2, info);
-				isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
-				return info->line;
+				(info->isdn_driver == -1) &&
+				(info->isdn_channel == -1) &&
+				(USG_NONE(dev->usage[idx]))) {
+				int matchret;
+
+				if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
+					wret = matchret;
+				if (!matchret) {                  /* EAZ is matching */
+					info->isdn_driver = di;
+					info->isdn_channel = ch;
+					info->drv_index = idx;
+					dev->m_idx[idx] = info->line;
+					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
+					dev->usage[idx] |= ((si1 != 1) || (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ? 
+						ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+					strcpy(dev->num[idx], nr);
+					strcpy(info->emu.cpn, eaz);
+					info->emu.mdmreg[REG_SI1I] = si2bit[si1];
+					info->emu.mdmreg[REG_PLAN] = setup.plan;
+					info->emu.mdmreg[REG_SCREEN] = setup.screen;
+					isdn_info_update();
+					restore_flags(flags);
+					printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
+					       info->line);
+					info->msr |= UART_MSR_RI;
+					isdn_tty_modem_result(2, info);
+					isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
+					return 1;
+				}
X 			}
X 		}
X 	}
-	printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
-	       dev->drv[di]->reject_bus ? "rejected" : "ignored");
X 	restore_flags(flags);
-	return -1;
+	printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
+	       ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");
+	return (wret == 2)?3:0;
X }
X 
X #define TTY_IS_ACTIVE(info) \
@@ -2128,7 +2489,7 @@
X                         case ISDN_STAT_CINF:
X                                 printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
X                                 info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
-                                if (e == c->parm.num)
+                                if (e == (char *)c->parm.num)
X 					info->emu.charge = 0;
X 				
X                                 break;			
@@ -2169,10 +2530,11 @@
X 				printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
X #endif
X 				if (TTY_IS_ACTIVE(info)) {
-					if (info->dialing == 1) {
-						info->dialing = 0;
+					if (info->dialing == 1) 
X 						isdn_tty_modem_result(7, info);
-					}
+					if (info->dialing > 1) 
+						isdn_tty_modem_result(3, info);
+					info->dialing = 0;
X #ifdef ISDN_DEBUG_MODEM_HUP
X 					printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
X #endif
@@ -2191,14 +2553,20 @@
X 				if (TTY_IS_ACTIVE(info)) {
X 					info->msr |= UART_MSR_DCD;
X 					info->emu.charge = 0;
-					if (info->dialing) {
-						info->dialing = 0;
+					if (info->dialing & 0xf)
X 						info->last_dir = 1;
-					} else
+					else
X 						info->last_dir = 0;
+					info->dialing = 0;
X 					info->rcvsched = 1;
-					if (USG_MODEM(dev->usage[i]))
-						isdn_tty_modem_result(5, info);
+					if (USG_MODEM(dev->usage[i])) {
+						if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
+							strcpy(info->emu.connmsg, c->parm.num);
+							isdn_tty_modem_result(1, info);
+						}
+						else
+							isdn_tty_modem_result(5, info);
+					}
X 					if (USG_VOICE(dev->usage[i]))
X 						isdn_tty_modem_result(11, info);
X 					return 1;
@@ -2228,11 +2596,7 @@
X 						sprintf(info->last_cause, "0000");
X 						isdn_tty_modem_result(6, info);
X 					}
-					info->msr &= ~UART_MSR_DCD;
-					if (info->online) {
-						isdn_tty_modem_result(3, info);
-						info->online = 0;
-					}
+					isdn_tty_modem_hup(info, 0);
X 					return 1;
X 				}
X 				break;
@@ -2393,7 +2757,7 @@
X 	 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
X 	 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
X 	ulong flags;
-	char s[10];
+	char s[ISDN_MSNLEN+10];
X 
X 	switch (code) {
X 		case 2:
@@ -2473,7 +2837,20 @@
X 			}
X 			isdn_tty_at_cout(msg[code], info);
X 			switch (code) {
+				case 1:
+					switch (m->mdmreg[REG_L2PROT]) {
+						case ISDN_PROTO_L2_MODEM:
+							isdn_tty_at_cout(" ", info);
+							isdn_tty_at_cout(m->connmsg, info);
+							break;
+					}
+					break;
X 				case 2:
+					/* Append CPN, if enabled */
+					if ((m->mdmreg[REG_RESRXT] & BIT_RESRXT)) {
+						sprintf(s, "/%s", m->cpn);
+						isdn_tty_at_cout(s, info);
+					}
X 					/* Print CID only once, _after_ 1.st RING */
X 					if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
X 					    (m->mdmreg[REG_RINGCNT] == 1)) {
@@ -2560,7 +2937,9 @@
X static void
X isdn_tty_get_msnstr(char *n, char **p)
X {
-	while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ','))
+	while ((*p[0] >= '0' && *p[0] <= '9') ||
+	       /* Why a comma ??? */
+	       (*p[0] == ','))
X 		*n++ = *p[0]++;
X 	*n = '\0';
X }
@@ -2626,6 +3005,9 @@
X 		case ISDN_PROTO_L2_TRANS:
X 			isdn_tty_at_cout("transparent", info);
X 			break;
+		case ISDN_PROTO_L2_MODEM:
+			isdn_tty_at_cout("modem", info);
+			break;
X 		default:
X 			isdn_tty_at_cout("unknown", info);
X 			break;
@@ -2668,6 +3050,8 @@
X 	int i;
X 	char rb[100];
X 
+#define MAXRB (sizeof(rb) - 1)
+
X 	switch (*p[0]) {
X 		case 'B':
X 			/* &B - Set Buffersize */
@@ -2719,6 +3103,15 @@
X 			isdn_tty_reset_profile(m);
X 			isdn_tty_modem_reset_regs(info, 1);
X 			break;
+		case 'L':
+			/* &L -Set Numbers to listen on */
+			p[0]++;
+			i = 0;
+			while ((strchr("0123456789,*[]?;", *p[0])) &&
+			       (i < ISDN_LMSNLEN))
+				m->lmsn[i++] = *p[0]++;
+			m->lmsn[i] = '\0';
+			break;
X 		case 'R':
X 			/* &R - Set V.110 bitrate adaption */
X 			p[0]++;
@@ -2774,6 +3167,11 @@
X 			sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
X 				strlen(m->msn) ? m->msn : "None");
X 			isdn_tty_at_cout(rb, info);
+			if (strlen(m->lmsn)) {
+				isdn_tty_at_cout("\r\nListen: ", info);
+				isdn_tty_at_cout(m->lmsn, info);
+				isdn_tty_at_cout("\r\n", info);
+			}
X 			break;
X 		case 'W':
X 			/* &W - Write Profile */
@@ -2939,9 +3337,10 @@
X #ifdef CONFIG_ISDN_AUDIO
X 		/* If more than one bit set in reg18, autoselect Layer2 */
X 		if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
-			if (m->mdmreg[REG_SI1I] == 1)
-				l2 = ISDN_PROTO_L2_TRANS;
-			else
+			if (m->mdmreg[REG_SI1I] == 1) {
+				if (l2 != ISDN_PROTO_L2_MODEM)
+					l2 = ISDN_PROTO_L2_TRANS;
+			} else
X 				l2 = ISDN_PROTO_L2_X75I;
X 		}
X #endif
@@ -2957,7 +3356,10 @@
X 		cmd.driver = info->isdn_driver;
X 		cmd.arg = info->isdn_channel;
X 		cmd.command = ISDN_CMD_ACCEPTD;
+		info->dialing = 16;
+		info->emu.carrierwait = 0;
X 		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
X 	} else
X 		isdn_tty_modem_result(8, info);
X }
@@ -3221,6 +3623,11 @@
X 				printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
X 				PARSE_ERROR1;
X 			}
+			info->silence_state = isdn_audio_silence_init(info->silence_state);
+			if (!info->silence_state) {
+				printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
+				PARSE_ERROR1;
+			}
X 			if (m->vpar[3] < 5) {
X 				info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
X 				if (!info->adpcmr) {
@@ -3247,31 +3654,27 @@
X 					break;
X 				case '=':
X 					p[0]++;
-					switch (*p[0]) {
-						case '0':
-						case '1':
-						case '2':
-						case '3':
-							par1 = isdn_getnum(p);
-							if ((par1 < 0) || (par1 > 31))
-								PARSE_ERROR1;
-							if (*p[0] != ',')
-								PARSE_ERROR1;
-							p[0]++;
-							par2 = isdn_getnum(p);
-							if ((par2 < 0) || (par2 > 255))
-								PARSE_ERROR1;
-							m->vpar[1] = par1;
-							m->vpar[2] = par2;
-							break;
-						case '?':
-							p[0]++;
-							isdn_tty_at_cout("\r\n<0-31>,<0-255>",
-								   info);
-							break;
-						default:
+					if ((*p[0]>='0') && (*p[0]<='9')) {
+						par1 = isdn_getnum(p);
+						if ((par1 < 0) || (par1 > 31))
X 							PARSE_ERROR1;
-					}
+						if (*p[0] != ',')
+							PARSE_ERROR1;
+						p[0]++;
+						par2 = isdn_getnum(p);
+						if ((par2 < 0) || (par2 > 255))
+							PARSE_ERROR1;
+						m->vpar[1] = par1;
+						m->vpar[2] = par2;
+						break;
+					} else 
+					if (*p[0] == '?') {
+						p[0]++;
+						isdn_tty_at_cout("\r\n<0-31>,<0-255>",
+							   info);
+						break;
+					} else
+					PARSE_ERROR1;
X 					break;
X 				default:
X 					PARSE_ERROR1;
@@ -3445,7 +3848,7 @@
X 				p++;
X 				if (info->msr & UART_MSR_DCD)
X 					/* if B-Channel is up */
-					isdn_tty_modem_result(5, info);
+					isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? 1:5, info);
X 				else
X 					isdn_tty_modem_result(3, info);
X 				return;
@@ -3486,29 +3889,46 @@
X 			case 'Z':
X 				/* Z - Load Registers from Profile */
X 				p++;
+				if (info->msr & UART_MSR_DCD) {
+					info->online = 0;
+					isdn_tty_on_hook(info);
+				}
X 				isdn_tty_modem_reset_regs(info, 1);
X 				break;
-#ifdef CONFIG_ISDN_AUDIO
X 			case '+':
X 				p++;
X 				switch (*p) {
+#ifdef CONFIG_ISDN_AUDIO
X 					case 'F':
X 						p++;
X 						if (isdn_tty_cmd_PLUSF(&p, info))
X 							return;
X 						break;
X 					case 'V':
-						if (!(m->mdmreg[REG_SI1] & 1))
+						if ((!(m->mdmreg[REG_SI1] & 1)) ||
+							(m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
X 							PARSE_ERROR;
X 						p++;
X 						if (isdn_tty_cmd_PLUSV(&p, info))
X 							return;
X 						break;
+#endif                          /* CONFIG_ISDN_AUDIO */
+					case 'S':	/* SUSPEND */
+						p++;
+						isdn_tty_get_msnstr(ds, &p);
+						isdn_tty_suspend(ds, info, m);
+						break;
+					case 'R':	/* RESUME */
+						isdn_tty_get_msnstr(ds, &p);
+						isdn_tty_resume(ds, info, m);
+					case 'M':	/* MESSAGE */
+						p++;
+						isdn_tty_send_msg(info, m, p);
+						break;
X 					default:
X 						PARSE_ERROR;
X 				}
X 				break;
-#endif                          /* CONFIG_ISDN_AUDIO */
X 			case '&':
X 				p++;
X 				if (isdn_tty_cmd_ATand(&p, info))
@@ -3672,4 +4092,29 @@
X 		}
X 	}
X 	isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
+}
+
+/*
+ * Check all channels if we have a 'no carrier' timeout.
+ * Timeout value is set by Register S7.
+ */
+void
+isdn_tty_carrier_timeout(void)
+{
+	int ton = 0;
+	int i;
+
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		modem_info *info = &dev->mdm.info[i];
+		if (info->dialing) {
+			if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
+				info->dialing = 0;
+				isdn_tty_modem_result(3, info);
+				isdn_tty_modem_hup(info, 1);
+			}
+			else
+				ton = 1;
+		}
+	}
+	isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h
--- v2.3.3/linux/drivers/isdn/isdn_tty.h	Thu May 29 21:53:06 1997
+++ linux/drivers/isdn/isdn_tty.h	Sun May 23 10:03:42 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_tty.h,v 1.10 1997/03/02 14:29:26 fritz Exp $
+/* $Id: isdn_tty.h,v 1.13 1999/04/12 12:33:46 fritz Exp $
X 
X  * header for Linux ISDN subsystem, tty related functions (linklevel).
X  *
- * Copyright 1994,95,96 by Fritz Elfert (fr...@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fr...@isdn4linux.de)
X  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
X  *
X  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,24 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdn_tty.h,v $
+ * Revision 1.13  1999/04/12 12:33:46  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.12 1999/03/02 12:04:51 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.11 1998/03/19 13:18:27 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
X  * Revision 1.10  1997/03/02 14:29:26  fritz
X  * More ttyI related cleanup.
X  *
@@ -56,6 +74,7 @@
X 
X extern void isdn_tty_modem_escape(void);
X extern void isdn_tty_modem_ring(void);
+extern void isdn_tty_carrier_timeout(void);
X extern void isdn_tty_modem_xmit(void);
X extern int isdn_tty_modem_init(void);
X extern void isdn_tty_readmodem(void);
@@ -63,3 +82,4 @@
X extern void isdn_tty_cleanup_xmit(modem_info *);
X extern int isdn_tty_stat_callback(int, isdn_ctrl *);
X extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
+extern int isdn_tty_capi_facility(capi_msg *cm); 
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdn_x25iface.c linux/drivers/isdn/isdn_x25iface.c
--- v2.3.3/linux/drivers/isdn/isdn_x25iface.c	Thu Jan  7 08:46:59 1999
+++ linux/drivers/isdn/isdn_x25iface.c	Sun May 23 10:03:42 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_x25iface.c,v 1.3 1998/02/20 17:25:20 fritz Exp $
+/* $Id: isdn_x25iface.c,v 1.6 1999/01/27 22:53:19 he Exp $
X  * stuff needed to support the Linux X.25 PLP code on top of devices that
X  * can provide a lab_b service using the concap_proto mechanism.
X  * This module supports a network interface wich provides lapb_sematics
@@ -10,6 +10,17 @@
X  * goes to another -- device related -- concap_proto support source file.
X  *
X  * $Log: isdn_x25iface.c,v $
+ * Revision 1.6  1999/01/27 22:53:19  he
+ * minor updates (spellings, jiffies wrap around in isdn_tty)
+ *
+ * Revision 1.5 1998/10/30 17:55:39 he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.4  1998/06/17 19:51:00  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
X * Revision 1.3 1998/02/20 17:25:20 fritz
X  * Changes for recent kernels.
X  *
@@ -302,7 +313,12 @@
X 	case 0x01: /* dl_connect request */
X 		if( *state == WAN_DISCONNECTED ){
X 			*state = WAN_CONNECTING;
-		        cprot -> dops -> connect_req(cprot);
+		        ret = cprot -> dops -> connect_req(cprot);
+			if(ret){
+				/* reset state and notify upper layer about
+				 * immidiatly failed attempts */
+				isdn_x25iface_disconn_ind(cprot);
+			}
X 		} else {
X 			illegal_state_warn( *state, firstbyte );
X 		}
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c
--- v2.3.3/linux/drivers/isdn/isdnloop/isdnloop.c	Sat Oct 31 10:37:14 1998
+++ linux/drivers/isdn/isdnloop/isdnloop.c	Sun May 23 10:03:42 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.4 1998/02/24 21:39:05 he Exp $
+/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $
X 
X  * ISDN low-level module implementing a dummy loop driver.
X  *
@@ -19,6 +19,20 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdnloop.c,v $
+ * Revision 1.8  1998/11/18 18:59:43  armin
+ * changes for 2.1.127
+ *
+ * Revision 1.7  1998/10/30 18:58:03  he
+ * typecast to suppress a compiler warning
+ *
+ * Revision 1.6  1998/06/17 19:51:37  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.5  1998/04/14 20:59:32  he
+ * merged 2.1.94 changes
+ *
X  * Revision 1.4  1998/02/24 21:39:05  he
X  * L2_PROT_X25DTE / DCE
X  * additional state 17 and new internal signal messages "BCON_I"
@@ -42,7 +56,7 @@
X #include "isdnloop.h"
X 
X static char
-*revision = "$Revision: 1.4 $";
+*revision = "$Revision: 1.8 $";
X 
X static int isdnloop_addcard(char *);
X 
@@ -1312,7 +1326,7 @@
X 							c->parm.num[0] ? "N" : "ALL", c->parm.num);
X 					} else
X 						sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
-							c->parm.num[0] ? c->parm.num : "0123456789");
+							c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");
X 					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
X 				}
X 				break;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/isdnloop/isdnloop.h linux/drivers/isdn/isdnloop/isdnloop.h
--- v2.3.3/linux/drivers/isdn/isdnloop/isdnloop.h	Tue Apr  7 07:52:04 1998
+++ linux/drivers/isdn/isdnloop/isdnloop.h	Sun May 23 10:03:42 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.h,v 1.2 1997/10/01 09:22:07 fritz Exp $
+/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $
X 
X  * Loopback lowlevel module for testing of linklevel.
X  *
@@ -19,6 +19,9 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
X  * $Log: isdnloop.h,v $
+ * Revision 1.3  1998/04/14 20:59:35  he
+ * merged 2.1.94 changes
+ *
X  * Revision 1.2  1997/10/01 09:22:07  fritz
X  * Removed old compatibility stuff for 2.0.X kernels.
X  * From now on, this code is for 2.1.X ONLY!
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/pcbit/callbacks.c linux/drivers/isdn/pcbit/callbacks.c
--- v2.3.3/linux/drivers/isdn/pcbit/callbacks.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/isdn/pcbit/callbacks.c	Sun May 23 10:03:42 1999
@@ -11,6 +11,13 @@
X  *        callbacks for the FSM
X  */
X 
+/*
+ * Fix: 19981230 - Carlos Morgado <ch...@techie.com>
+ * Port of Nelson Escravana's <nelson.e...@usa.net> fix to CalledPN 
+ * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
+ */
+
+
X #define __NO_VERSION__
X 
X #include <linux/module.h>
@@ -164,12 +171,24 @@
X          *  ictl.num >= strlen() + strlen() + 5
X          */
X 
+	if (cbdata->data.setup.CallingPN == NULL) {
+		printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n");
+		strcpy(ictl.parm.setup.phone, "0");
+	}
+	else {
X 		strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN);
+	}
+	if (cbdata->data.setup.CalledPN == NULL) {
+		printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n");
+		strcpy(ictl.parm.setup.eazmsn, "0");
+	}
+	else {
X 		strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN);
-		ictl.parm.setup.si1 = 7;
-		ictl.parm.setup.si2 = 0;
-		ictl.parm.setup.plan = 0;
-		ictl.parm.setup.screen = 0;
+	}
+	ictl.parm.setup.si1 = 7;
+	ictl.parm.setup.si2 = 0;
+	ictl.parm.setup.plan = 0;
+	ictl.parm.setup.screen = 0;
X 
X #ifdef DEBUG
X 	printk(KERN_DEBUG "statstr: %s\n", ictl.num);
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c
--- v2.3.3/linux/drivers/isdn/pcbit/drv.c	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/pcbit/drv.c	Sun May 23 10:03:42 1999
@@ -86,6 +86,9 @@
X 
X 	dev_pcbit[board] = dev;
X 	memset(dev, 0, sizeof(struct pcbit_dev));
+#if LINUX_VERSION_CODE >= 131841
+	init_waitqueue_head(&dev->set_running_wq);
+#endif
X 
X 	if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF )
X 		dev->sh_mem = (unsigned char*) mem_base;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/pcbit/pcbit.h linux/drivers/isdn/pcbit/pcbit.h
--- v2.3.3/linux/drivers/isdn/pcbit/pcbit.h	Mon May 17 09:55:22 1999
+++ linux/drivers/isdn/pcbit/pcbit.h	Sun May 23 10:03:42 1999
@@ -68,7 +68,11 @@
X 	struct frame_buf *write_queue;
X 
X 	/* Protocol start */
+#if LINUX_VERSION_CODE < 131841
+	struct wait_queue *set_running_wq;
+#else
X 	wait_queue_head_t set_running_wq;
+#endif
X 	struct timer_list set_running_timer;
X 
X 	struct timer_list error_recover_timer;
diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/sc/message.c linux/drivers/isdn/sc/message.c
--- v2.3.3/linux/drivers/isdn/sc/message.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/sc/message.c	Sun May 23 10:03:42 1999
@@ -1,5 +1,5 @@
X /*
- *  $Id: message.c,v 1.3 1998/01/31 22:10:55 keil Exp $
+ *  $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $
X  *  Copyright (C) 1996  SpellCaster Telecommunications Inc.
X  *
X  *  message.c - functions for sending and receiving control messages
diff -u --recursive --new-file v2.3.3/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c
--- v2.3.3/linux/drivers/misc/parport_init.c	Mon May 17 09:55:22 1999
+++ linux/drivers/misc/parport_init.c	Sat May 22 15:02:48 1999
@@ -22,7 +22,7 @@
X static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
X static int io_hi[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
X static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
-static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
+static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_AUTO };
X 
X extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma);
X extern int parport_ax_init(void);
@@ -146,8 +146,11 @@
X EXPORT_SYMBOL(parport_claim_or_block);
X EXPORT_SYMBOL(parport_release);
X EXPORT_SYMBOL(parport_register_port);
+EXPORT_SYMBOL(parport_announce_port);
X EXPORT_SYMBOL(parport_unregister_port);
X EXPORT_SYMBOL(parport_quiesce);
+EXPORT_SYMBOL(parport_register_driver);
+EXPORT_SYMBOL(parport_unregister_driver);
X EXPORT_SYMBOL(parport_register_device);
X EXPORT_SYMBOL(parport_unregister_device);
X EXPORT_SYMBOL(parport_enumerate);
@@ -157,6 +160,7 @@
X EXPORT_SYMBOL(parport_proc_unregister);
X EXPORT_SYMBOL(parport_probe_hook);
X EXPORT_SYMBOL(parport_parse_irqs);
+EXPORT_SYMBOL(parport_parse_dmas);
X 
X void inc_parport_count(void)
X {
diff -u --recursive --new-file v2.3.3/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.3.3/linux/drivers/misc/parport_pc.c	Mon May 17 09:55:22 1999
+++ linux/drivers/misc/parport_pc.c	Sat May 22 15:02:48 1999
@@ -44,6 +44,7 @@
X #include <linux/ioport.h>
X #include <linux/kernel.h>
X #include <linux/malloc.h>
+#include <linux/pci.h>
X 
X #include <asm/io.h>
X 
@@ -847,9 +848,59 @@
X 	if (parport_probe_hook)
X 		(*parport_probe_hook)(p);
X 
+	/* Now that we've told the sharing engine about the port, and
+	   found out its characteristics, let the high-level drivers
+	   know about it. */
+	parport_announce_port (p);
+
X 	return 1;
X }
X 
+/* Look for PCI parallel port cards. */
+static int __init parport_pc_init_pci (int irq, int dma)
+{
+	int count = 0;
+#ifdef CONFIG_PCI
+	int i;
+	struct {
+		unsigned int vendor;
+		unsigned int device;
+		unsigned int numports;
+		struct {
+			unsigned int lo;
+			unsigned int hi; /* -ve if not there */
+		} addr[4];
+	} cards[] = {
+		{ 0, }
+	};
+
+	if (!pci_present ())
+		return 0;
+
+	for (i = 0; cards[i].vendor; i++) {
+		struct pci_dev *pcidev = NULL;
+		while ((pcidev = pci_find_device (cards[i].vendor,
+						  cards[i].device,
+						  pcidev)) != NULL) {
+			int n;
+			for (n = 0; n < cards[i].numports; n++) {
+				int lo = cards[i].addr[n].lo;
+				int hi = cards[i].addr[n].hi;
+				int io_lo = pcidev->base_address[lo];
+				int io_hi = ((hi < 0) ? 0 :
+					     pcidev->base_address[hi]);
+				io_lo &= PCI_BASE_ADDRESS_IO_MASK;
+				io_hi &= PCI_BASE_ADDRESS_IO_MASK;
+				count += probe_one_port (io_lo, io_hi,
+							 irq, dma);
+			}
+		}
+	}
+#endif /* CONFIG_PCI */
+
+	return count;
+}
+
X int __init parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
X {
X 	int count = 0, i = 0;
@@ -866,6 +917,7 @@
X 		count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
X 		count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
X 		count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
+		count += parport_pc_init_pci (irq[0], dma[0]);
X 	}
X 
X 	return count;
@@ -874,13 +926,22 @@
X #ifdef MODULE
X static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
X static int io_hi[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
-static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
+static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
X static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
X static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
+static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
+
+MODULE_PARM_DESC(io, "base address");
X MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+
+MODULE_PARM_DESC(io_hi, "base address for ECR");
X MODULE_PARM(io_hi, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+
+MODULE_PARM_DESC(irq, "irq line to use (or 'auto' or 'none')");
X MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+
+MODULE_PARM_DESC(dma, "dma channel to use (or 'auto' or 'none')");
+MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
X 
X int init_module(void)
X {	
@@ -888,9 +949,30 @@
X 	   the irq values. */
X 	unsigned int i;
X 	for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
-	parport_parse_irqs(i, irq, irqval);
+	if (i) {
+		if (parport_parse_irqs(i, irq, irqval)) return 1;
+		if (parport_parse_dmas(i, dma, dmaval)) return 1;
+	}
+	else {
+		/* The user can make us use any IRQs or DMAs we find. */
+		int val;
+
+		if (irq[0] && !parport_parse_irqs (1, irq, &val))
+			switch (val) {
+			case PARPORT_IRQ_NONE:
+			case PARPORT_IRQ_AUTO:
+				irqval[0] = val;
+			}
+
+		if (dma[0] && !parport_parse_dmas (1, dma, &val))
+			switch (val) {
+			case PARPORT_DMA_NONE:
+			case PARPORT_DMA_AUTO:
+				dmaval[0] = val;
+			}
+	}
X 
-	return (parport_pc_init(io, io_hi, irqval, dma)?0:1);
+	return (parport_pc_init(io, io_hi, irqval, dmaval)?0:1);
X }
X 
X void cleanup_module(void)
diff -u --recursive --new-file v2.3.3/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.3.3/linux/drivers/misc/parport_share.c	Fri May 14 18:55:19 1999
+++ linux/drivers/misc/parport_share.c	Sat May 22 15:02:48 1999
@@ -40,6 +40,55 @@
X static struct parport *portlist = NULL, *portlist_tail = NULL;
X spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
X 
+static struct parport_driver *driver_chain = NULL;
+spinlock_t driverlist_lock = SPIN_LOCK_UNLOCKED;
+
+static void call_driver_chain (int attach, struct parport *port)
+{
+	struct parport_driver *drv;
+
+	for (drv = driver_chain; drv; drv = drv->next) {
+		if (attach)
+			drv->attach (port);
+		else
+			drv->detach (port);
+	}
+}
+
+int parport_register_driver (struct parport_driver *drv)
+{
+	struct parport *port;
+
+	spin_lock (&driverlist_lock);
+	drv->next = driver_chain;
+	driver_chain = drv;
+	spin_unlock (&driverlist_lock);
+
+	for (port = portlist; port; port = port->next)
+		drv->attach (port);
+
+	return 0;
+}
+
+void parport_unregister_driver (struct parport_driver *arg)
+{
+	struct parport_driver *drv = driver_chain, *olddrv = NULL;
+
+	while (drv) {
+		if (drv == arg) {
+			spin_lock (&driverlist_lock);
+			if (olddrv)
+				olddrv->next = drv->next;
+			else
+				driver_chain = drv->next;
+			spin_unlock (&driverlist_lock);
+			return;
+		}
+		olddrv = drv;
+		drv = drv->next;
+	}
+}
+
X void (*parport_probe_hook)(struct parport *port) = NULL;
X 
X /* Return a list of all the ports we know about. */
@@ -138,10 +187,19 @@
X 	return tmp;
X }
X 
+void parport_announce_port (struct parport *port)
+{
+	/* Let drivers know that a new port has arrived. */
+	call_driver_chain (1, port);
+}
+
X void parport_unregister_port(struct parport *port)
X {
X 	struct parport *p;
X 
+	/* Spread the word. */
+	call_driver_chain (0, port);
+
X 	spin_lock(&parportlist_lock);
X 	if (portlist == port) {
X 		if ((portlist = port->next) == NULL)
@@ -517,23 +575,38 @@
X 	}
X }
X 
-void parport_parse_irqs(int nports, const char *irqstr[], int irqval[])
+static int parport_parse_params (int nports, const char *str[], int val[],
+				 int automatic, int none)
X {
X 	unsigned int i;
-	for (i = 0; i < nports && irqstr[i]; i++) {
-		if (!strncmp(irqstr[i], "auto", 4))
-			irqval[i] = PARPORT_IRQ_AUTO;
-		else if (!strncmp(irqstr[i], "none", 4))
-			irqval[i] = PARPORT_IRQ_NONE;
+	for (i = 0; i < nports && str[i]; i++) {
+		if (!strncmp(str[i], "auto", 4))
+			val[i] = automatic;
+		else if (!strncmp(str[i], "none", 4))
+			val[i] = none;
X 		else {
X 			char *ep;
-			unsigned long r = simple_strtoul(irqstr[i], &ep, 0);
-			if (ep != irqstr[i])
-				irqval[i] = r;
+			unsigned long r = simple_strtoul(str[i], &ep, 0);
+			if (ep != str[i])
+				val[i] = r;
X 			else {
-				printk("parport: bad irq specifier `%s'\n", irqstr[i]);
-				return;
+				printk("parport: bad specifier `%s'\n", str[i]);
+				return -1;
X 			}
X 		}
X 	}
+
+	return 0;
+}
+
+int parport_parse_irqs(int nports, const char *irqstr[], int irqval[])
+{
+	return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO,
+				     PARPORT_IRQ_NONE);
+}
+
+int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[])
+{
+	return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO,
+				     PARPORT_DMA_NONE);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.3.3/linux/drivers/net/Space.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/net/Space.c	Tue May 25 13:06:34 1999
@@ -805,3 +805,4 @@
X };
X 
X struct device *dev_base = &loopback_dev;
+rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
diff -u --recursive --new-file v2.3.3/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.3.3/linux/drivers/net/arcnet.c	Mon Sep 14 11:32:22 1998
+++ linux/drivers/net/arcnet.c	Tue May 25 13:06:34 1999
@@ -2023,8 +2023,10 @@
X   for (c=0; c< (arcnet_num_devs-1); c++)
X     arcnet_devs[c].next=&arcnet_devs[c+1];
X 
+  write_lock_bh(&dev_base_lock);
X   arcnet_devs[c].next=dev_base;
X   dev_base=&arcnet_devs[0];
+  write_unlock_bh(&dev_base_lock);
X 
X   /* Give names to those without them */
X 
@@ -2078,9 +2080,11 @@
X   for (;;)
X     {
X       sprintf(device, "arc%d", arcnum);
+      read_lock_bh(&dev_base_lock);
X       for (dev = dev_base; dev; dev=dev->next)
X 	if (dev->name != device && !strcmp(dev->name, device))
X 	  break;
+      read_unlock_bh(&dev_base_lock);
X       if (!dev)
X 	return;
X       arcnum++;
diff -u --recursive --new-file v2.3.3/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.3.3/linux/drivers/net/cosa.c	Mon May 17 09:55:22 1999
+++ linux/drivers/net/cosa.c	Sun May 30 10:18:20 1999
@@ -2,6 +2,9 @@
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
@@ -599,6 +602,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;
@@ -750,8 +754,8 @@
X 
X static void chardev_channel_init(struct channel_data *chan)
X {
-	chan->rsem = MUTEX;
-	chan->wsem = MUTEX;
+	init_MUTEX(&chan->rsem);
+	init_MUTEX(&chan->wsem);
X }
X 
X static long long cosa_lseek(struct file * file,
diff -u --recursive --new-file v2.3.3/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.3.3/linux/drivers/net/eexpress.c	Thu May  6 23:14:36 1999
+++ linux/drivers/net/eexpress.c	Sun May 30 10:18:49 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.3.3/linux/drivers/net/hamradio/bpqether.c linux/drivers/net/hamradio/bpqether.c
--- v2.3.3/linux/drivers/net/hamradio/bpqether.c	Sat Jul 18 14:16:03 1998
+++ linux/drivers/net/hamradio/bpqether.c	Tue May 25 13:06:34 1999
@@ -641,11 +641,16 @@
X 	});
X #endif
X 
+	read_lock_bh(&dev_base_lock);
X 	for (dev = dev_base; dev != NULL; dev = dev->next) {
-		if (dev_is_ethdev(dev))
+		if (dev_is_ethdev(dev)) {
+			read_unlock_bh(&dev_base_lock);
X 			bpq_new_device(dev);
+			read_lock_bh(&dev_base_lock);
+		}
X 	}
-
+	read_unlock_bh(&dev_base_lock);
+out:
X 	return 0;
X }
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.3.3/linux/drivers/net/irda/Config.in	Sun Mar  7 15:26:43 1999
+++ linux/drivers/net/irda/Config.in	Sun May 30 10:27:03 1999
@@ -1,18 +1,24 @@
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
+
+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.3.3/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.3.3/linux/drivers/net/irda/Makefile	Thu Apr 15 05:42:41 1999
+++ linux/drivers/net/irda/Makefile	Sun May 30 10:27:03 1999
@@ -20,6 +20,14 @@
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
+
X ifeq ($(CONFIG_NSC_FIR),y)
X L_OBJS += pc87108.o
X else
@@ -44,6 +52,14 @@
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
+
X ifeq ($(CONFIG_ESI_DONGLE),y)
X L_OBJS += esi.o
X else
@@ -73,6 +89,14 @@
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
X   endif
X endif
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.3.3/linux/drivers/net/irda/actisys.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/actisys.c	Sun May 30 10:27:03 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:   Mon May 10 15:12:54 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 
@@ -36,15 +36,14 @@
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, int unused);
+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_reset(struct irda_device *dev, int unused);
+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 +57,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 +97,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 +112,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;);
-	
-	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;);
-
X 	current_baudrate = idev->qos.baud_rate.value;
X 
X 	/* Find the correct baudrate index for the currently used baudrate */
@@ -117,69 +130,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 +169,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, int unused)
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 +193,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 +217,7 @@
X  */
X int init_module(void)
X {
-	actisys_init();
-	return(0);
+	return actisys_init();
X }
X 
X /*
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.3.3/linux/drivers/net/irda/esi.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/esi.c	Sun May 30 10:27:03 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:   Mon May 10 15:13:12 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
@@ -41,11 +41,11 @@
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, int unused);
+static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
X 
X static struct dongle dongle = {
X 	ESI_DONGLE,
@@ -58,17 +58,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 +76,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,54 +90,30 @@
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;
-	
-	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;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
-	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 
X static void esi_reset( struct irda_device *idev, int unused)
@@ -148,14 +127,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.3.3/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.3.3/linux/drivers/net/irda/girbil.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/girbil.c	Sun May 30 10:27:03 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:   Mon May 10 16:01:33 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -80,19 +80,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 +100,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 +117,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)
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 30'
echo 'File patch-2.3.4 is continued in part 31'
echo 31 > _shar_seq_.tmp
#!/bin/sh
# this is part 31 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 31; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
-		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 /*
@@ -193,44 +167,32 @@
X  */
X void girbil_reset(struct irda_device *idev, int unused)
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;
X 	schedule_timeout(2);
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;
X 	schedule_timeout(2);
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;
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 
X /*
@@ -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.3.3/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.3.3/linux/drivers/net/irda/irport.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/irport.c	Sun May 30 10:27:03 1999
@@ -64,58 +64,168 @@
X 
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 void irport_wait_until_sent(struct irda_device *idev);
+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;
+
+	/* 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);
+		/* w83977af_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)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
X 
+	/* Release the 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(int iobase)
+{
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);
@@ -123,24 +233,29 @@
X 	/* Turn on interrups */
X 	outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER);
X 
-	return 0;
+}
+
+void irport_stop(int iobase)
+{
+	/* Reset UART */
+	outb(0, iobase+UART_MCR);
+	
+	/* Turn off interrupts */
+	outb(0, iobase+UART_IER);
X }
X 
X /*
- * Function irport_cleanup ()
+ * Function irport_probe (void)
X  *
- *    Stop IO port
+ *    Start IO port 
X  *
X  */
-void irport_close(int iobase) 
+int irport_probe(int iobase)
X {
-	DEBUG(4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
X 
-	/* Reset UART */
-	outb(0, iobase+UART_MCR);
X 
-	/* Turn off interrupts */
-	outb(0, iobase+UART_IER);
+	return 0;
X }
X 
X /*
@@ -149,14 +264,23 @@
X  *    Set speed of 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 {
+	int iobase; 
X 	int fcr;    /* FIFO control reg */
X 	int lcr;    /* Line control reg */
X 	int divisor;
X 
X 	DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
X 
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase2;
+	
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
X 	/* Turn off interrupts */
X 	outb(0, iobase+UART_IER); 
X 
@@ -373,8 +497,145 @@
X 	idev->netdev.interrupt = 0;
X }
X 
+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;
+	}
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	MOD_INC_USE_COUNT;
+
+	irport_start(iobase);
+
+	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;
+
+	irport_stop(iobase);
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	free_irq(idev->io.irq2, idev);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static void irport_wait_until_sent(struct irda_device *idev)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(60*HZ/1000);
+}
+
+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 #ifdef MODULE
X 
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(irq, "1-4i");
+
X /*
X  * Function cleanup_module (void)
X  *
@@ -393,11 +654,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.3.3/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.3.3/linux/drivers/net/irda/irtty.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/irtty.c	Sun May 30 10:27:04 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 
@@ -38,19 +38,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 +75,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 +127,6 @@
X 	 *  function to hashbin_destroy().
X 	 */
X 	hashbin_delete(irtty, NULL);
-	hashbin_delete(dongles, NULL);
X }
X #endif /* MODULE */
X 
@@ -201,7 +195,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 +210,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 +243,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 +350,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 +381,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 +574,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 +616,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 +676,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.3.3/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.3.3/linux/drivers/net/irda/litelink.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/litelink.c	Sun May 30 10:27:04 1999
@@ -0,0 +1,209 @@
+/*********************************************************************
+ *                
+ * 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:   Mon May 10 15:12:18 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 <asm/ioctls.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/dongle.h>
+
+static void litelink_reset(struct irda_device *dev, int unused);
+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, int unused);
+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(15);
+
+	/* Go back to normal mode */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+	
+	/* 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(15);
+		
+		/* Set DTR, Set RTS */
+		irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		
+		/* Sleep a minimum of 15 us */
+		udelay(15);
+        }
+}
+
+/*
+ * 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, int unused)
+{
+	struct irtty_cb *self;
+        struct tty_struct *tty;
+
+	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(15);
+
+	/* Clear RTS to reset dongle */
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+
+	/* Go back to normal mode */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+
+	/* 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.3.3/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.3/linux/drivers/net/irda/pc87108.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/pc87108.c	Sun May 30 10:27:04 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:   Sun May  9 12:57:46 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,6 +67,7 @@
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 
@@ -219,7 +220,7 @@
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;
+	idev->qos.min_turn_time.bits = qos_mtt_bits;
X 	irda_qos_bits_to_value( &idev->qos);
X 	
X 	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
@@ -259,8 +260,9 @@
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");
@@ -269,13 +271,16 @@
X 	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 */
X 	DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", 
X 	       idev->io.iobase);
-	release_region( idev->io.iobase, idev->io.io_ext);
+	release_region(idev->io.iobase, idev->io.io_ext);
+
+	irda_device_close(idev);
X 
-	irda_device_close( idev);
+	kfree(self);
X 
X 	return 0;
X }
@@ -805,7 +810,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  */ 
@@ -973,7 +977,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 +992,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 +1005,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 +1190,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 +1461,11 @@
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");
X 
X /*
X  * Function init_module (void)
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.3.3/linux/drivers/net/irda/tekram.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/tekram.c	Sun May 30 10:27:04 1999
@@ -1,15 +1,15 @@
X /*********************************************************************
X  *                
X  * Filename:      tekram.c
- * Version:       1.0
+ * Version:       1.1
X * Description: Implementation of the Tekram IrMate IR-210B dongle
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Tue Apr 13 16:33:54 1999
+ * Modified at:   Mon May 10 16:10:17 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 
@@ -62,15 +62,15 @@
X 
X __initfunc(int tekram_init(void))
X {
-	return irtty_register_dongle(&dongle);
+	return irda_device_register_dongle(&dongle);
X }
X 
X void tekram_cleanup(void)
X {
-	irtty_unregister_dongle( &dongle);
+	irda_device_unregister_dongle(&dongle);
X }
X 
-static void tekram_open( struct irda_device *idev, int type)
+static void tekram_open(struct irda_device *idev, int type)
X {
X 	strcat(idev->description, " <-> tekram");
X 
@@ -80,8 +80,11 @@
X 	MOD_INC_USE_COUNT;
X }
X 
-static void tekram_close( struct irda_device *dev)
-{
+static void tekram_close(struct irda_device *idev)
+{		
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
X 	MOD_DEC_USE_COUNT;
X }
X 
@@ -101,79 +104,49 @@
X  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
X  *       after
X  */
-static void tekram_change_speed( struct irda_device *dev, int baud)
+static void tekram_change_speed(struct irda_device *idev, int baud)
X {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
-	struct termios old_termios;
-	int cflag;
X 	__u8 byte;
X 	
X 	DEBUG(4, __FUNCTION__ "()\n");
X 
-	ASSERT(dev != NULL, return;);
-	ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) dev->priv;
-	
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
-	if (!self->tty)
-		return;
-
-	tty = self->tty;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
X 	switch (baud) {
X 	default:
-		/* FALLTHROUGH */
X 	case 9600:
-		cflag |= B9600;
X 		byte = TEKRAM_PW|TEKRAM_9600;
X 		break;
X 	case 19200:
-		cflag |= B19200;
X 		byte = TEKRAM_PW|TEKRAM_19200;
X 		break;
X 	case 34800:
-		cflag |= B38400;
X 		byte = TEKRAM_PW|TEKRAM_38400;
X 		break;
X 	case 57600:
-		cflag |= B57600;
X 		byte = TEKRAM_PW|TEKRAM_57600;
X 		break;
X 	case 115200:
-		cflag |= B115200;
X 		byte = TEKRAM_PW|TEKRAM_115200;
X 		break;
X 	}
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 least 7us */
X 	udelay(7);
X 
X 	/* Write control byte */
-	if (tty->driver.write)
-		tty->driver.write(self->tty, 0, &byte, 1);
+	irda_device_raw_write(idev, &byte, 1);
X 	
X 	/* Wait at least 100 ms */
X 	current->state = TASK_INTERRUPTIBLE;
X schedule_timeout(MSECS_TO_JIFFIES(100));
X         
X 	/* Set DTR, Set RTS */
-	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 /*
@@ -189,41 +162,27 @@
X  *        3. clear DTR to SPACE state, wait at least 50 us for further 
X  *         operation
X  */
-void tekram_reset(struct irda_device *dev, int unused)
+void tekram_reset(struct irda_device *idev, int unused)
X {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(dev != NULL, return;);
-	ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) dev->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 	/* Power off dongle */
-	irtty_set_dtr_rts(tty, FALSE, FALSE);
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
X 
X 	/* Sleep 50 ms */
X 	current->state = TASK_INTERRUPTIBLE;
X 	schedule_timeout(MSECS_TO_JIFFIES(50));
X 
X 	/* Clear DTR, Set RTS */
-	irtty_set_dtr_rts(tty, FALSE, TRUE); 
+	irda_device_set_dtr_rts(idev, FALSE, TRUE); 
X 
X /* Should sleep 1 ms, but 10-20 should not do any harm */
X 	current->state = TASK_INTERRUPTIBLE;
X schedule_timeout(MSECS_TO_JIFFIES(20));
X 
X 	/* Set DTR, Set RTS */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
X 	
X 	udelay(50);
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.3/linux/drivers/net/irda/toshoboe.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/toshoboe.c	Sun May 30 10:27:04 1999
@@ -0,0 +1,901 @@
+/*********************************************************************
+ *                
+ * Filename:      toshoboe.c
+ * Version:       0.1
+ * Description:   Driver for the Toshiba OBOE (or type-O or 700 or 701)
+ *                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
+ *     Toshiba refers to this chip as the type-O IR port.
+ *
+ ********************************************************************/
+
+/* This driver is experimental, I have only three ir devices */
+/* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
+/* an hp printer, this works fine at 4MBPS with my HP printer */
+
+static char *rcsid = "$Id: toshoboe.c,v 1.5 1999/05/12 12:24:39 root Exp root $";
+
+/* 
+ * $Log: toshoboe.c,v $
+ * Revision 1.5  1999/05/12 12:24:39  root
+ * *** empty log message ***
+ *
+ * Revision 1.4  1999/05/12 11:55:08  root
+ * *** empty log message ***
+ *
+ * Revision 1.3  1999/05/09 01:33:12  root
+ * *** empty log message ***
+ *
+ * Revision 1.2  1999/05/09 01:30:38  root
+ * *** empty log message ***
+ *
+ * Revision 1.1  1999/05/09 01:25:04  root
+ * Initial revision
+ * 
+ */
+
+/* Define this to have only one frame in the XMIT or RECV queue */
+/* Toshiba's drivers do this, but it disables back to back tansfers */
+/* I think that the chip may have some problems certainly, I have */
+/* seen it jump over tasks in the taskfile->xmit with this turned on */
+#define ONETASK
+
+/* To adjust the number of tasks in use edit toshoboe.h */
+
+/* Define this to enable FIR and MIR support */
+#define ENABLE_FAST
+
+/* Number of ports this driver can support, you also need to edit dev_self below */
+#define NSELFS 4
+
+/* Size of IO window */
+#define CHIP_IO_EXTENT	0x1f
+
+/* Transmit and receive buffer sizes, adjust at your peril */
+#define RX_BUF_SZ 	4196
+#define TX_BUF_SZ	4196
+
+/* No user servicable parts below here */
+
+#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/init.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.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/toshoboe.h>
+
+static char *driver_name = "toshoboe";
+
+static struct toshoboe_cb *dev_self[NSELFS + 1] =
+{NULL, NULL, NULL, NULL, NULL};
+
+/* Shutdown the chip and point the taskfile reg somewhere else */
+static void 
+toshoboe_stopchip (struct toshoboe_cb *self)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  outb_p (0x0e, OBOE_REG_11);
+
+  outb_p (0x00, OBOE_RST);
+  outb_p (0x3f, OBOE_TFP2);     /*Write the taskfile address */
+  outb_p (0xff, OBOE_TFP1);
+  outb_p (0xff, OBOE_TFP0);
+  outb_p (0x0f, OBOE_REG_1B);
+  outb_p (0xff, OBOE_REG_1A);
+  outb_p (0x00, OBOE_ISR);      /*FIXME: should i do this to disbale ints */
+  outb_p (0x80, OBOE_RST);
+  outb_p (0xe, OBOE_LOCK);
+}
+
+/*Set the baud rate */
+static void 
+toshoboe_setbaud (struct toshoboe_cb *self, int baud)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
+
+  cli ();
+  switch (baud)
+    {
+    case 2400:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0xbf, OBOE_UDIV);
+      break;
+    case 4800:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x5f, OBOE_UDIV);
+      break;
+    case 9600:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x2f, OBOE_UDIV);
+      break;
+    case 19200:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x17, OBOE_UDIV);
+      break;
+    case 38400:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0xb, OBOE_UDIV);
+      break;
+    case 57600:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x7, OBOE_UDIV);
+      break;
+    case 115200:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x3, OBOE_UDIV);
+      break;
+    case 1152000:
+      outb_p (OBOE_PMDL_MIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_MIR, OBOE_SMDL);
+      outb_p (0x1, OBOE_UDIV);
+      break;
+    case 4000000:
+      outb_p (OBOE_PMDL_FIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_FIR, OBOE_SMDL);
+      outb_p (0x0, OBOE_UDIV);
+      break;
+    }
+
+  sti ();
+
+  outb_p (0x00, OBOE_RST);
+  outb_p (0x80, OBOE_RST);
+  outb_p (0x01, OBOE_REG_9);
+
+}
+
+/* Wake the chip up and get it looking at the taskfile */
+static void 
+toshoboe_startchip (struct toshoboe_cb *self)
+{
+  __u32 physaddr;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+
+  outb_p (0, OBOE_LOCK);
+  outb_p (0, OBOE_RST);
+  outb_p (OBOE_NTR_VAL, OBOE_NTR);
+  outb_p (0xf0, OBOE_REG_D);
+  outb_p (0xff, OBOE_ISR);
+  outb_p (0x0f, OBOE_REG_1A);
+  outb_p (0xff, OBOE_REG_1B);
+
+
+  physaddr = virt_to_bus (self->taskfile);
+
+  outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0);
+  outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1);
+  outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
+
+  outb_p (0x0e, OBOE_REG_11);
+  outb_p (0x80, OBOE_RST);
+
+  toshoboe_setbaud (self, 9600);
+
+}
+
+/*Let the chip look at memory */
+static void 
+toshoboe_enablebm (struct toshoboe_cb *self)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+  pci_set_master (self->pdev);
+}
+
+/*Don't let the chip look at memory */
+static void 
+toshoboe_disablebm (struct toshoboe_cb *self)
+{
+  __u8 command;
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
+  command &= ~PCI_COMMAND_MASTER;
+  pci_write_config_byte (self->pdev, PCI_COMMAND, command);
+
+}
+
+/*setup the taskfile */
+static void 
+toshoboe_initbuffs (struct toshoboe_cb *self)
+{
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  cli ();
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      self->taskfile->xmit[i].len = 0;
+      self->taskfile->xmit[i].control = 0x00;
+      self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]);
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      self->taskfile->recv[i].len = 0;
+      self->taskfile->recv[i].control = 0x83;
+      self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
+    }
+
+  sti ();
+}
+
+
+/*Transmit something */
+static int 
+toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev)
+{
+  struct irda_device *idev;
+  struct toshoboe_cb *self;
+  int mtt, len;
+
+  idev = (struct irda_device *) dev->priv;
+  ASSERT (idev != NULL, return 0;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return 0;);
+
+
+#ifdef ONETASK
+  if (self->txpending)
+    return -EBUSY;
+
+  self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
+
+  self->txs &= 0x3f;
+
+#endif
+
+  if (self->taskfile->xmit[self->txs].control)
+    return -EBUSY;
+
+
+  if (inb_p (OBOE_RST) & OBOE_RST_WRAP)
+    {
+      len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ);
+    }
+  else
+    {
+      len = skb->len;
+      memcpy (self->xmit_bufs[self->txs], skb->data, len);
+    }
+  self->taskfile->xmit[self->txs].len = len & 0x0fff;
+
+
+
+  outb_p (0, OBOE_RST);
+  outb_p (0x1e, OBOE_REG_11);
+
+  self->taskfile->xmit[self->txs].control = 0x84;
+
+  mtt = irda_get_mtt (skb);
+  if (mtt)
+    udelay (mtt);
+
+  self->txpending++;
+
+  /*FIXME: ask about tbusy,media_busy stuff, for the moment */
+  /*tbusy means can't queue any more */
+#ifndef ONETASK
+  if (self->txpending == TX_SLOTS)
+    {
+#else
+  {
+#endif
+    if (irda_lock ((void *) &dev->tbusy) == FALSE)
+      return -EBUSY;
+  }
+
+  outb_p (0x80, OBOE_RST);
+  outb_p (1, OBOE_REG_9);
+
+  self->txs++;
+  self->txs %= TX_SLOTS;
+
+  dev_kfree_skb (skb);
+
+  return 0;
+}
+
+/*interrupt handler */
+static void 
+toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct irda_device *idev = (struct irda_device *) dev_id;
+  struct toshoboe_cb *self;
+  __u8 irqstat;
+  struct sk_buff *skb;
+
+  if (idev == NULL)
+    {
+      printk (KERN_WARNING "%s: irq %d for unknown device.\n",
+              driver_name, irq);
+      return;
+    }
+
+  self = idev->priv;
+
+  if (!self)
+    return;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  irqstat = inb_p (OBOE_ISR);
+
+/* woz it us */
+  if (!(irqstat & 0xf8))
+    return;
+
+  outb_p (irqstat, OBOE_ISR);   /*Acknologede it */
+
+
+/* Txdone */
+  if (irqstat & OBOE_ISR_TXDONE)
+    {
+      self->txpending--;
+
+      idev->stats.tx_packets++;
+
+      idev->media_busy = FALSE;
+      idev->netdev.tbusy = 0;
+
+      mark_bh (NET_BH);
+    }
+
+  if (irqstat & OBOE_ISR_RXDONE)
+    {
+
+#ifdef ONETASK
+      self->rxs = inb_p (OBOE_RCVT);
+      self->rxs += (RX_SLOTS - 1);
+      self->rxs %= RX_SLOTS;
+#else
+      while (self->taskfile->recv[self->rxs].control == 0)
+#endif
+        {
+          int len = self->taskfile->recv[self->rxs].len;
+	
+	  if (len>2) len-=2;
+
+          skb = dev_alloc_skb (len + 1);
+          if (skb)
+            {
+              skb_reserve (skb, 1);
+
+              skb_put (skb, len);
+              memcpy (skb->data, self->recv_bufs[self->rxs], len);
+
+              idev->stats.rx_packets++;
+              skb->dev = &idev->netdev;
+              skb->mac.raw = skb->data;
+              skb->protocol = htons (ETH_P_IRDA);
+            }
+          else
+            {
+              printk (KERN_INFO __FUNCTION__
+                      "(), memory squeeze, dropping frame.\n");
+            }
+
+
+
+          self->taskfile->recv[self->rxs].control = 0x83;
+          self->taskfile->recv[self->rxs].len = 0x0;
+
+          self->rxs++;
+          self->rxs %= RX_SLOTS;
+
+          if (skb)
+            netif_rx (skb);
+
+        }
+
+    }
+
+  if (irqstat & OBOE_ISR_20)
+    {
+      printk (KERN_WARNING "Oboe_irq: 20\n");
+    }
+  if (irqstat & OBOE_ISR_10)
+    {
+      printk (KERN_WARNING "Oboe_irq: 10\n");
+    }
+  if (irqstat & 0x8)
+    {
+      /*FIXME: I think this is a TX or RX error of some sort */
+
+      idev->stats.tx_errors++;
+      idev->stats.rx_errors++;
+
+    }
+
+
+}
+
+
+
+/* Change the baud rate */
+static void 
+toshoboe_change_speed (struct irda_device *idev, int speed)
+{
+  struct toshoboe_cb *self;
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (idev != NULL, return;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return;);
+
+  idev->io.baudrate = speed;
+
+  toshoboe_setbaud (self, speed);
+
+}
+
+
+/* Check all xmit_tasks finished */
+static void 
+toshoboe_wait_until_sent (struct irda_device *idev)
+{
+  struct toshoboe_cb *self;
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (idev != NULL, return;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return;);
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      while (self->taskfile->xmit[i].control)
+        {
+          current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout (6);
+        }
+    }
+
+}
+
+static int 
+toshoboe_is_receiving (struct irda_device *idev)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+/*FIXME Can't tell! */
+  return (FALSE);
+}
+
+
+static int 
+toshoboe_net_init (struct device *dev)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  /* Setup to be a normal IrDA network device driver */
+  irda_device_setup (dev);
+
+  /* Insert overrides below this line! */
+  return 0;
+}
+
+
+
+
+static int 
+toshoboe_net_open (struct device *dev)
+{
+  struct irda_device *idev;
+  struct toshoboe_cb *self;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (dev != NULL, return -1;);
+  idev = (struct irda_device *) dev->priv;
+
+  ASSERT (idev != NULL, return 0;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return 0;);
+
+  if (request_irq (idev->io.irq, toshoboe_interrupt,
+                   SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev))
+    {
+
+      return -EAGAIN;
+    }
+
+  toshoboe_initbuffs (self);
+  toshoboe_enablebm (self);
+  toshoboe_startchip (self);
+
+
+  cli ();
+
+  /*FIXME: need to test this carefully to check which one */
+  /*of the two possible startup logics the chip uses */
+  /*although it won't make any difference if no-one xmits durining init */
+  /*and none what soever if using ONETASK */
+
+  self->rxs = inb_p (OBOE_RCVT);
+  self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
+
+#ifdef 0
+  self->rxs = 0;
+  self->txs = 0;
+#endif
+#ifdef 0
+  self->rxs = RX_SLOTS - 1;
+  self->txs = 0;
+#endif
+
+
+  self->txpending = 0;
+
+  sti ();
+
+
+  dev->tbusy = 0;
+  dev->interrupt = 0;
+  dev->start = 1;
+
+  MOD_INC_USE_COUNT;
+
+  return 0;
+
+}
+
+static int 
+toshoboe_net_close (struct device *dev)
+{
+  struct irda_device *idev;
+  struct toshoboe_cb *self;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (dev != NULL, return -1;);
+  idev = (struct irda_device *) dev->priv;
+
+  ASSERT (idev != NULL, return 0;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+  dev->tbusy = 1;
+  dev->start = 0;
+
+
+  self = idev->priv;
+
+  ASSERT (self != NULL, return 0;);
+
+  free_irq (idev->io.irq, (void *) idev);
+
+  toshoboe_stopchip (self);
+  toshoboe_disablebm (self);
+
+  MOD_DEC_USE_COUNT;
+
+  return 0;
+
+}
+
+
+
+#ifdef MODULE
+
+static int 
+toshoboe_close (struct irda_device *idev)
+{
+  struct toshoboe_cb *self;
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (idev != NULL, return -1;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+  self = idev->priv;
+
+  ASSERT (self != NULL, return -1;);
+
+  toshoboe_stopchip (self);
+
+  release_region (idev->io.iobase, idev->io.io_ext);
+
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      kfree (self->xmit_bufs[i]);
+      self->xmit_bufs[i] = NULL;
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      kfree (self->recv_bufs[i]);
+      self->recv_bufs[i] = NULL;
+    }
+
+
+  kfree (self->taskfilebuf);
+  self->taskfilebuf = NULL;
+  self->taskfile = NULL;
+
+
+  irda_device_close (idev);
+
+  return (0);
+
+}
+
+#endif
+
+
+
+static int 
+toshoboe_open (struct pci_dev *pci_dev)
+{
+  struct toshoboe_cb *self;
+  struct irda_device *idev;
+  int i = 0;
+  int ok=0;
+
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  while (dev_self[i])
+    i++;
+
+  if (i == NSELFS)
+    {
+      printk (KERN_ERR "Oboe: No more instances available");
+      return -ENOMEM;
+    }
+
+  self = kmalloc (sizeof (struct toshoboe_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 toshoboe_cb));
+
+
+  dev_self[i] = self;
+
+  self->pdev = pci_dev;
+  self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+
+  idev = &self->idev;
+
+  /*Setup idev */
+
+  idev->io.iobase = self->base;
+  idev->io.irq = pci_dev->irq;
+  idev->io.io_ext = CHIP_IO_EXTENT;
+
+  /* Lock the port that we need */
+  i = check_region (idev->io.iobase, idev->io.io_ext);
+  if (i < 0)
+    {
+      DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+             idev->io.iobase);
+
+      dev_self[i] = NULL;
+      kfree (self);
+
+      return -ENODEV;
+    }
+
+  request_region (idev->io.iobase, idev->io.io_ext, driver_name);
+
+  irda_init_max_qos_capabilies (&idev->qos);
+
+  idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 |
+    IR_115200;
+#ifdef ENABLE_FAST
+ idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8);
+#endif
+
+  idev->qos.min_turn_time.bits = 0xff;  /*FIXME: what does this do? */
+
+  irda_qos_bits_to_value (&idev->qos);
+
+  idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+
+#ifdef ENABLE_FAST
+  idev->flags |= IFF_FIR;
+#endif
+
+  /* These aren't much use as we need to have a whole panoply of
+   * buffers running */
+
+  idev->rx_buff.flags = 0;
+  idev->tx_buff.flags = 0;
+  idev->rx_buff.truesize = 0;
+  idev->rx_buff.truesize = 0;
+
+  idev->change_speed = toshoboe_change_speed;
+  idev->wait_until_sent = toshoboe_wait_until_sent;
+  idev->is_receiving = toshoboe_is_receiving;
+
+  idev->netdev.init = toshoboe_net_init;
+  idev->netdev.hard_start_xmit = toshoboe_hard_xmit;
+  idev->netdev.open = toshoboe_net_open;
+  idev->netdev.stop = toshoboe_net_close;
+
+
+  /* Now setup the endless buffers we need */
+
+  self->txs = 0;
+  self->rxs = 0;
+
+  self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL | GFP_DMA);
+  if (!self->taskfilebuf) {
+	printk(KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
+	kfree(self);
+	return -ENOMEM;
+  }
+
+
+  memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
+
+  /*We need to align the taskfile on a taskfile size boundary */
+  {
+    __u32 addr;
+
+    addr = (__u32) self->taskfilebuf;
+    addr &= ~(sizeof (struct OboeTaskFile) - 1);
+    addr += sizeof (struct OboeTaskFile);
+
+    self->taskfile = (struct OboeTaskFile *) addr;
+  }
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
+      if (self->xmit_bufs[i]) ok++;
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
+      if (self->recv_bufs[i]) ok++;
+    }
+
+  if (ok!=RX_SLOTS+TX_SLOTS) {
+	printk(KERN_ERR  "toshoboe: kmalloc for buffers failed()\n");
+
+
+  for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree(self->xmit_bufs[i]);
+  for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree(self->recv_bufs[i]);
+
+	kfree(self);
+	return -ENOMEM;
+
+  }
+
+
+  irda_device_open (idev, driver_name, self);
+
+  printk (KERN_WARNING "ToshOboe: Using ");
+#ifdef ONETASK
+  printk ("single");
+#else
+  printk ("multiple");
+#endif
+  printk (" tasks, version %s\n", rcsid);
+
+  return (0);
+}
+
+__initfunc (int toshoboe_init (void))
+{
+  struct pci_dev *pci_dev = NULL;
+  int found = 0;
+
+  do
+    {
+      pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA,
+                                 PCI_DEVICE_ID_FIR701, pci_dev);
+      if (pci_dev)
+        {
+          printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n",
+                  pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK,
+                  pci_dev->irq);
+
+          if (!toshoboe_open (pci_dev))
+            found++;
+        }
+
+    }
+  while (pci_dev);
+
+  if (found)
+    return 0;
+
+  return -ENODEV;
+}
+
+#ifdef MODULE
+
+static void 
+toshoboe_cleanup (void)
+{
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  for (i = 0; i < 4; i++)
+    {
+      if (dev_self[i])
+        toshoboe_close (&(dev_self[i]->idev));
+    }
+}
+
+
+
+int 
+init_module (void)
+{
+  return toshoboe_init ();
+}
+
+
+void 
+cleanup_module (void)
+{
+  toshoboe_cleanup ();
+}
+
+
+#endif
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.3.3/linux/drivers/net/irda/uircc.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/uircc.c	Sun May 30 10:27:04 1999
@@ -7,10 +7,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Tue Apr 20 11:15:52 1999
+ * Modified at:   Mon May 10 22:11:09 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 
@@ -216,7 +216,7 @@
X 	idev->netdev.open            = uircc_net_open;
X 	idev->netdev.stop            = uircc_net_close;
X 
-	irport_open(iobase2);
+	irport_start(iobase2);
X 
X 	/* Open the IrDA device */
X 	irda_device_open(idev, driver_name, self);
@@ -233,6 +233,7 @@
X #ifdef MODULE
X static int uircc_close(struct irda_device *idev)
X {
+	struct uircc_cb *self;
X 	int iobase;
X 	int status;
X 
@@ -242,6 +243,7 @@
X 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
X 
X         iobase = idev->io.iobase;
+	self = (struct uircc_cb *) idev->priv;
X 
X 	/* Some magic to disable FIR and enable SIR */
X 	uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
@@ -249,7 +251,7 @@
X 	/* Disable modem */
X 	outb(0x00, iobase+UIRCC_CR10);
X 
-	irport_close(idev->io.iobase2);
+	irport_stop(idev->io.iobase2);
X 
X 	/* Release the PORT that this driver is using */
X 	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
@@ -262,6 +264,8 @@
X 	}
X 	irda_device_close(idev);
X 
+	kfree(self);
+
X 	return 0;
X }
X #endif /* MODULE */
@@ -346,8 +350,8 @@
X 	case 37600:
X 	case 57600:
X 	case 115200:
- 		irport_open(idev->io.iobase2);
-		irport_change_speed( idev->io.iobase2, speed);
+ 		irport_start(idev->io.iobase2);
+		irport_change_speed(idev, speed);
X 
X 		/* Some magic to disable FIR and enable SIR */
X 		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
@@ -363,7 +367,7 @@
X 		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
X 		break;
X 	case 4000000:
-		irport_close(idev->io.iobase2);
+		irport_stop(idev->io.iobase2);
X 
X 		/* Some magic to disable SIR and enable FIR */
X 		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001);
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.3/linux/drivers/net/irda/w83977af_ir.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/net/irda/w83977af_ir.c	Sun May 30 10:27:04 1999
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 31'
echo 'File patch-2.3.4 is continued in part 32'
echo 32 > _shar_seq_.tmp
#!/bin/sh
# this is part 32 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 32; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
@@ -1,16 +1,16 @@
X /*********************************************************************
X  *                
X  * Filename:      w83977af_ir.c
- * Version:       0.8
- * Description:   FIR/MIR driver for the Winbond W83977AF Super I/O chip
+ * Version:       1.0
+ * Description:   FIR driver for the Winbond W83977AF Super I/O chip
X  * Status:        Experimental.
X  * Author:        Paul VanderSpek
X  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Tue Apr 20 11:15:00 1999
+ * Modified at:   Thu May 13 08:03:27 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
+ *     Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>
X * Copyright (c) 1998 Corel Computer Corp.
- *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>
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 
@@ -40,7 +40,7 @@
X  ********************************************************************/
X 
X #include <linux/module.h>
-
+ 
X #include <linux/kernel.h>
X #include <linux/types.h>
X #include <linux/skbuff.h>
@@ -61,44 +61,45 @@
X #include <net/irda/w83977af.h>
X #include <net/irda/w83977af_ir.h>
X 
-#define NETWINDER
+#define CONFIG_NETWINDER                 /* Adjust to NetWinder differences */
+#undef  CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
+#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
+#undef  CONFIG_USE_INTERNAL_TIMER        /* Just cannot make that timer work */
+#define CONFIG_USE_W977_PNP              /* Currently needed */
+#define PIO_MAX_SPEED       115200 
X 
X static char *driver_name = "w83977af_ir";
+static int  qos_mtt_bits = 0x07;           /* 1 ms or more */
X 
X #define CHIP_IO_EXTENT 8
X 
X static unsigned int io[] = { 0x180, ~0, ~0, ~0 };
X static unsigned int irq[] = { 6, 0, 0, 0 };
-static unsigned int dma[] = { 0, 0, 0, 0 };
-
-static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static unsigned int dma[] = 
+{ 1, 0, 0, 0 };
X 
-/* For storing entries in the status FIFO */
-struct st_fifo_entry {
-	int status;
-	int len;
-};
+static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
X 
X static struct st_fifo_entry prev;
X 
X /* Some prototypes */
-static int  w83977af_open( int i, unsigned int iobase, unsigned int irq, 
-			   unsigned int dma);
-static int  w83977af_close( struct irda_device *idev);
-static int  w83977af_probe( int iobase, int irq, int dma);
+static int  w83977af_open(int i, unsigned int iobase, unsigned int irq, 
+                          unsigned int dma);
+static int  w83977af_close(struct irda_device *idev);
+static int  w83977af_probe(int iobase, int irq, int dma);
X static int  w83977af_dma_receive(struct irda_device *idev); 
X static int  w83977af_dma_receive_complete(struct irda_device *idev);
-static int  w83977af_hard_xmit( struct sk_buff *skb, struct device *dev);
-static int  w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
-static void w83977af_dma_write( struct irda_device *idev, int iobase);
-static void w83977af_change_speed( struct irda_device *idev, int baud);
+static int  w83977af_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void w83977af_dma_write(struct irda_device *idev, int iobase);
+static void w83977af_change_speed(struct irda_device *idev, int baud);
X static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void w83977af_wait_until_sent( struct irda_device *idev);
-static int w83977af_is_receiving( struct irda_device *idev);
+static void w83977af_wait_until_sent(struct irda_device *idev);
+static int  w83977af_is_receiving(struct irda_device *idev);
X 
-static int w83977af_net_init( struct device *dev);
-static int w83977af_net_open( struct device *dev);
-static int w83977af_net_close( struct device *dev);
+static int  w83977af_net_init(struct device *dev);
+static int  w83977af_net_open(struct device *dev);
+static int  w83977af_net_close(struct device *dev);
X 
X /*
X  * Function w83977af_init ()
@@ -108,13 +109,13 @@
X  */
X __initfunc(int w83977af_init(void))
X {
-	int i;
+        int i;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
X 
X 	prev.status = 0;
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;
@@ -135,11 +136,11 @@
X {
X 	int i;
X 
- DEBUG( 4, __FUNCTION__ "()\n");
+        DEBUG(4, __FUNCTION__ "()\n");
X 
-	for ( i=0; i < 4; i++) {
-		if ( dev_self[i])
-			w83977af_close( dev_self[i]);
+	for (i=0; i < 4; i++) {
+		if (dev_self[i])
+ w83977af_close(&(dev_self[i]->idev));
X 	}
X }
X #endif /* MODULE */
@@ -154,26 +155,29 @@
X 		   unsigned int dma)
X {
X 	struct irda_device *idev;
+        struct w83977af_ir *self;
X 	int ret;
X 
X 	DEBUG( 0, __FUNCTION__ "()\n");
X 
-	if ( w83977af_probe( iobase, irq, dma) == -1)
+	if (w83977af_probe(iobase, irq, dma) == -1)
X 		return -1;
X 
X 	/*
X 	 *  Allocate new instance of the driver
X 	 */
-	idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL);
-	if ( idev == NULL) {
+	self = kmalloc(sizeof(struct w83977af_ir), GFP_KERNEL);
+	if (self == NULL) {
X 		printk( KERN_ERR "IrDA: Can't allocate memory for "
X 			"IrDA control block!\n");
X 		return -ENOMEM;
X 	}
-	memset( idev, 0, sizeof(struct irda_device));
+	memset(self, 0, sizeof(struct w83977af_ir));
X    
X 	/* Need to store self somewhere */
-	dev_self[i] = idev;
+	dev_self[i] = self;
+
+	idev = &self->idev;
X 
X 	/* Initialize IO */
X 	idev->io.iobase    = iobase;
@@ -183,17 +187,17 @@
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) { 
+	ret = check_region(idev->io.iobase, idev->io.io_ext);
+	if (ret < 0) { 
X 		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
X 		       idev->io.iobase);
X 		/* w83977af_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 
@@ -202,8 +206,8 @@
X 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
X 
X 	/* The HP HDLS-1100 needs 1 ms according to the specs */
-	idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
-	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;
X 
@@ -221,13 +225,13 @@
X         idev->is_receiving    = w83977af_is_receiving;
X 
X 	/* Override the network functions we need to use */
-	idev->netdev.init = w83977af_net_init;
+	idev->netdev.init            = w83977af_net_init;
X 	idev->netdev.hard_start_xmit = w83977af_hard_xmit;
-	idev->netdev.open = w83977af_net_open;
-	idev->netdev.stop = w83977af_net_close;
+	idev->netdev.open            = w83977af_net_open;
+	idev->netdev.stop            = w83977af_net_close;
X 
X 	/* Open the IrDA device */
-	irda_device_open( idev, driver_name, NULL);
+	irda_device_open(idev, driver_name, self);
X 	
X 	return 0;
X }
@@ -240,15 +244,18 @@
X  */
X static int w83977af_close( struct irda_device *idev)
X {
+	struct w83977af_ir *self;
X 	int iobase;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __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 w83977af_ir *) idev->priv;
X 
+#ifdef CONFIG_USE_W977_PNP
X 	/* enter PnP configuration mode */
X 	w977_efm_enter();
X 
@@ -258,13 +265,15 @@
X 	w977_write_reg(0x30, 0x00);
X 
X 	w977_efm_exit();
-
+#endif /* CONFIG_USE_W977_PNP */
X 	/* Release the PORT that this driver is using */
X 	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
X 	      idev->io.iobase);
-	release_region( idev->io.iobase, idev->io.io_ext);
+	release_region(idev->io.iobase, idev->io.io_ext);
+
+	irda_device_close(idev);
X 
-	irda_device_close( idev);
+	kfree(self);
X 
X 	return 0;
X }
@@ -280,7 +289,7 @@
X 	int version;
X 	
X 	DEBUG( 0, __FUNCTION__ "()\n");
-
+#ifdef CONFIG_USE_W977_PNP
X 	/* Enter PnP configuration mode */
X 	w977_efm_enter();
X 
@@ -289,14 +298,14 @@
X 	/* Configure PnP port, IRQ, and DMA channel */
X 	w977_write_reg(0x60, (iobase >> 8) & 0xff);
X 	w977_write_reg(0x61, (iobase) & 0xff);
-	/* w977_write_reg(0x70, 0x06); */
+
X 	w977_write_reg(0x70, irq);
-#ifdef NETWINDER
-	w977_write_reg(0x74, dma+1); /* Netwinder uses one higher than Linux */
+#ifdef CONFIG_NETWINDER
+	w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */
X #else
X 	w977_write_reg(0x74, dma);   
X #endif
-	w977_write_reg(0x75, dma);   /* Disable Tx DMA */
+	w977_write_reg(0x75, 0x04);  /* Disable Tx DMA */
X 	
X 	/* Set append hardware CRC, enable IR bank selection */	
X 	w977_write_reg(0xf0, APEDCRC|ENBNKSEL);
@@ -305,26 +314,26 @@
X 	w977_write_reg(0x30, 0x01);
X 
X 	w977_efm_exit();
-
+#endif
X  	/* Disable Advanced mode */
- 	switch_bank( iobase, SET2);
+ 	switch_bank(iobase, SET2);
X  	outb(iobase+2, 0x00);  
X 
X 	/* Turn on UART (global) interrupts */
-	switch_bank( iobase, SET0);
-	outb( HCR_EN_IRQ, iobase+HCR);
+	switch_bank(iobase, SET0);
+	outb(HCR_EN_IRQ, iobase+HCR);
X 	
X 	/* Switch to advanced mode */
-	switch_bank( iobase, SET2);
-	outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
+	switch_bank(iobase, SET2);
+	outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
X 
X 	/* Set default IR-mode */
-	switch_bank( iobase, SET0);
-	outb( HCR_SIR, iobase+HCR);
+	switch_bank(iobase, SET0);
+	outb(HCR_SIR, iobase+HCR);
X 
X 	/* Read the Advanced IR ID */
X 	switch_bank(iobase, SET3);
-	version =  inb( iobase+AUID);
+	version = inb(iobase+AUID);
X 	
X 	/* Should be 0x1? */
X 	if (0x10 != (version & 0xf0)) {
@@ -333,18 +342,17 @@
X 	}
X 	
X 	/* Set FIFO size to 32 */
-	switch_bank( iobase, SET2);
-	outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+	switch_bank(iobase, SET2);
+	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
X 	
X 	/* Set FIFO threshold to TX17, RX16 */
X 	switch_bank(iobase, SET0);	
X 	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR);
-/* 	outb( 0xa7, iobase+UFR); */
X 
X 	/* Receiver frame length */
-	switch_bank( iobase, SET4);
-	outb( 2048 & 0xff, iobase+6);
-	outb(( 2048 >> 8) & 0x1f, iobase+7);
+	switch_bank(iobase, SET4);
+	outb(2048 & 0xff, iobase+6);
+	outb((2048 >> 8) & 0x1f, iobase+7);
X 
X 	/* 
X 	 * Init HP HSDL-1100 transceiver. 
@@ -358,8 +366,8 @@
X 	 *   FIRRX pin 39 connected to receiver      (IRSL0) 
X 	 *   CIRRX pin 40 connected to pin 37
X 	 */
-	switch_bank( iobase, SET7);
-	outb( 0x40, iobase+7);
+	switch_bank(iobase, SET7);
+	outb(0x40, iobase+7);
X 		
X 	DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
X 	
@@ -372,16 +380,14 @@
X  *    Change the speed of the device
X  *
X  */
-void w83977af_change_speed( struct irda_device *idev, int speed)
+void w83977af_change_speed(struct irda_device *idev, int speed)
X {
X 	int ir_mode = HCR_SIR;
X 	int iobase; 
X 	__u8 set;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X 
X 	iobase = idev->io.iobase;
X 
@@ -389,22 +395,22 @@
X 	idev->io.baudrate = speed;
X 
X 	/* Save current bank */
-	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 
X 	/* Select Set 2 */
-	switch_bank( iobase, SET2);
+	switch_bank(iobase, SET2);
+	outb(0x00, iobase+ABHL);
X 
-	outb( 0x00, iobase+ABHL);
-	switch ( speed) {
-	case 9600:   outb( 0x0c, iobase+ABLL); break;
-	case 19200:  outb( 0x06, iobase+ABLL); break;
-	case 37600:  outb( 0x03, iobase+ABLL); break;
-	case 57600:  outb( 0x02, iobase+ABLL); break;
-	case 115200: outb( 0x01, iobase+ABLL); break;
+	switch (speed) {
+	case 9600:   outb(0x0c, iobase+ABLL); break;
+	case 19200:  outb(0x06, iobase+ABLL); break;
+	case 37600:  outb(0x03, iobase+ABLL); break;
+	case 57600:  outb(0x02, iobase+ABLL); break;
+	case 115200: outb(0x01, iobase+ABLL); break;
X 	case 576000:
X 		ir_mode = HCR_MIR_576;
X 		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
@@ -419,34 +425,37 @@
X 		break;
X 	default:
X 		ir_mode = HCR_FIR;
-		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
X 		break;
X 	}
X 
X 	/* Set speed mode */
X 	switch_bank(iobase, SET0);
-	outb( ir_mode, iobase+HCR);
+	outb(ir_mode, iobase+HCR);
X 
X 	/* set FIFO size to 32 */
-	switch_bank( iobase, SET2);
-	outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+	switch_bank(iobase, SET2);
+	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
X 	
X 	/* set FIFO threshold to TX17, RX16 */
X 	switch_bank(iobase, SET0);
-	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
-	
+
+	outb(0x00, iobase+UFR);        /* Reset */
+	outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
+	outb(0xa7, iobase+UFR);
+
X 	idev->netdev.tbusy = 0;
X 	
X 	/* Enable some interrupts so we can receive frames */
X 	switch_bank(iobase, SET0);
-	if ( speed > 115200) {
-		outb( ICR_EFSFI, iobase+ICR);
-		w83977af_dma_receive( idev);
+	if (speed > PIO_MAX_SPEED) {
+		outb(ICR_EFSFI, iobase+ICR);
+		w83977af_dma_receive(idev);
X 	} else
-		outb( ICR_ERBRI, iobase+ICR);
+		outb(ICR_ERBRI, iobase+ICR);
X     	
X 	/* Restore SSR */
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
X }
X 
X /*
@@ -455,7 +464,7 @@
X  *    Sets up a DMA transfer to send the current frame.
X  *
X  */
-int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev)
+int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev)
X {
X 	struct irda_device *idev;
X 	int iobase;
@@ -474,20 +483,21 @@
X 	/* Lock transmit buffer */
X 	if (irda_lock((void *) &dev->tbusy) == FALSE)
X 		return -EBUSY;
-	
+
X 	/* Save current set */
X 	set = inb(iobase+SSR);
X 	
X 	/* Decide if we should use PIO or DMA transfer */
-	if (idev->io.baudrate > 115200) {
+	if (idev->io.baudrate > PIO_MAX_SPEED) {
+		idev->tx_buff.data = idev->tx_buff.head;
X 		memcpy(idev->tx_buff.data, skb->data, skb->len);
X 		idev->tx_buff.len = skb->len;
-		idev->tx_buff.data = idev->tx_buff.head;
X 		
X 		mtt = irda_get_mtt(skb);
+#ifdef CONFIG_USE_INTERNAL_TIMER
X 	        if (mtt > 50) {
X 			/* Adjust for timer resolution */
-			mtt = mtt / 1000 + 1;
+			mtt /= 1000+1;
X 
X 			/* Setup timer */
X 			switch_bank(iobase, SET4);
@@ -502,6 +512,8 @@
X 			switch_bank(iobase, SET0);
X 			outb(ICR_ETMRI, iobase+ICR);
X 		} else {
+#endif
+			DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
X 			if (mtt)
X 				udelay(mtt);
X 
@@ -509,7 +521,9 @@
X 			switch_bank(iobase, SET0);
X 	 		outb(ICR_EDMAI, iobase+ICR);
X 	     		w83977af_dma_write(idev, iobase);
+#ifdef CONFIG_USE_INTERNAL_TIMER
X 		}
+#endif
X 	} else {
X 		idev->tx_buff.data = idev->tx_buff.head;
X 		idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
@@ -527,41 +541,57 @@
X 	return 0;
X }
X 
-
X /*
X  * Function w83977af_dma_write (idev, iobase)
X  *
- *    
+ *    Send frame using DMA
X  *
X  */
-static void w83977af_dma_write( struct irda_device *idev, int iobase)
+static void w83977af_dma_write(struct irda_device *idev, int iobase)
X {
X 	__u8 set;
-
-        DEBUG( 4, __FUNCTION__ "()\n");
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+	unsigned long flags;
+	__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 +607,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 +627,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 +647,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 +693,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 +704,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);
X 
-#ifdef NETWINDER
+	/* 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;
+
+#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 +771,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 +790,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 +840,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 +870,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 +916,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 +929,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 +942,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 +965,6 @@
X 
X 			new_icr |= ICR_ETBREI;
X 		}
-		
X 	}
X 	/* Check if transmission has completed */
X 	if (isr & ISR_TXEMP_I) {
@@ -943,22 +990,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 +1027,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 +1043,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 +1078,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 +1097,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 +1118,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 +1133,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 +1159,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 +1178,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 +1195,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 +1218,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 +1243,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 +1278,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.3.3/linux/drivers/net/lapbether.c linux/drivers/net/lapbether.c
--- v2.3.3/linux/drivers/net/lapbether.c	Fri Feb 20 18:28:22 1998
+++ linux/drivers/net/lapbether.c	Tue May 25 13:06:34 1999
@@ -533,10 +533,15 @@
X 
X 	printk(KERN_INFO "LAPB Ethernet driver version 0.01\n");
X 
+	read_lock_bh(&dev_base_lock);
X 	for (dev = dev_base; dev != NULL; dev = dev->next) {
-		if (dev_is_ethdev(dev))
+		if (dev_is_ethdev(dev)) {
+			read_unlock_bh(&dev_base_lock);
X 			lapbeth_new_device(dev);
+			read_lock_bh(&dev_base_lock);
+		}
X 	}
+	read_unlock_bh(&dev_base_lock);
X 
X 	return 0;
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.3.3/linux/drivers/net/net_init.c	Sat Apr 24 17:51:48 1999
+++ linux/drivers/net/net_init.c	Tue May 25 13:06:34 1999
@@ -91,9 +91,11 @@
X 		for (i = 0; i < MAX_ETH_CARDS; ++i)
X 			if (ethdev_index[i] == NULL) {
X 				sprintf(pname, "eth%d", i);
-				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
+				read_lock_bh(&dev_base_lock);
+				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
X 					if (strcmp(pname, cur_dev->name) == 0) {
X 						dev = cur_dev;
+						read_unlock_bh(&dev_base_lock);
X 						dev->init = NULL;
X 						sizeof_priv = (sizeof_priv + 3) & ~3;
X 						dev->priv = sizeof_priv
@@ -102,6 +104,8 @@
X 						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
X 						goto found;
X 					}
+				}
+				read_unlock_bh(&dev_base_lock);
X 			}
X 
X 		alloc_size &= ~3;		/* Round to dword boundary. */
@@ -209,9 +213,11 @@
X 		for (i = 0; i < MAX_HIP_CARDS; ++i)
X 			if (hipdev_index[i] == NULL) {
X 				sprintf(pname, "hip%d", i);
-				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
+				read_lock_bh(&dev_base_lock);
+				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
X 					if (strcmp(pname, cur_dev->name) == 0) {
X 						dev = cur_dev;
+						read_unlock_bh(&dev_base_lock);
X 						dev->init = NULL;
X 						sizeof_priv = (sizeof_priv + 3) & ~3;
X 						dev->priv = sizeof_priv
@@ -220,6 +226,8 @@
X 						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
X 						goto hipfound;
X 					}
+				}
+				read_unlock_bh(&dev_base_lock);
X 			}
X 
X 		alloc_size &= ~3;		/* Round to dword boundary. */
@@ -536,9 +544,11 @@
X 		for (i = 0; i < MAX_TR_CARDS; ++i)
X 			if (trdev_index[i] == NULL) {
X 				sprintf(pname, "tr%d", i);
-				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
+				read_lock_bh(&dev_base_lock);
+				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
X 					if (strcmp(pname, cur_dev->name) == 0) {
X 						dev = cur_dev;
+						read_unlock_bh(&dev_base_lock);
X 						dev->init = NULL;
X 						sizeof_priv = (sizeof_priv + 3) & ~3;
X 						dev->priv = sizeof_priv
@@ -547,6 +557,8 @@
X 						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
X 						goto trfound;
X 					}
+				}
+				read_unlock_bh(&dev_base_lock);
X 			}
X 
X 		alloc_size &= ~3;		/* Round to dword boundary. */
diff -u --recursive --new-file v2.3.3/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.3.3/linux/drivers/net/smc-ultra.c	Wed Feb 24 16:27:54 1999
+++ linux/drivers/net/smc-ultra.c	Wed May 26 09:31:50 1999
@@ -483,9 +483,9 @@
X 			/* NB: ultra_close_card() does free_irq + irq2dev */
X 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
X 			kfree(dev->priv);
-			dev->priv = NULL;
X 			release_region(ioaddr, ULTRA_IO_EXTENT);
X 			unregister_netdev(dev);
+			dev->priv = NULL;
X 		}
X 	}
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.3.3/linux/drivers/net/strip.c	Sun Nov  8 13:48:06 1998
+++ linux/drivers/net/strip.c	Tue May 25 13:06:34 1999
@@ -2027,7 +2027,9 @@
X         !memcmp(strip_info->dev.dev_addr, zero_address.c, sizeof(zero_address)) &&
X         memcmp(&strip_info->true_dev_addr, zero_address.c, sizeof(zero_address)))
X     {
-        struct device *dev = dev_base;
+        struct device *dev;
+	read_lock_bh(&dev_base_lock);
+	dev = dev_base;
X         while (dev)
X         {
X             if (dev->type == strip_info->dev.type &&
@@ -2035,10 +2037,12 @@
X             {
X                 printk(KERN_INFO "%s: Transferred packet ownership to %s.\n",
X                     strip_info->dev.name, dev->name);
+		read_unlock_bh(&dev_base_lock);
X                 return(dev);
X             }
X             dev = dev->next;
X         }
+	read_unlock_bh(&dev_base_lock);
X     }
X     return(&strip_info->dev);
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.3/linux/drivers/net/sunhme.c	Mon May 17 09:55:22 1999
+++ linux/drivers/net/sunhme.c	Thu May 27 09:55:21 1999
@@ -1597,9 +1597,9 @@
X 				      unsigned long status)
X {
X 	int reset = 0;
-
+	
X 	/* Only print messages for non-counter related interrupts. */
-	if(status & (GREG_STAT_RFIFOVF | GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND |
+	if(status & (GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND |
X 		     GREG_STAT_MAXPKTERR | GREG_STAT_RXERR |
X 		     GREG_STAT_RXPERR | GREG_STAT_RXTERR | GREG_STAT_EOPERR |
X 		     GREG_STAT_MIFIRQ | GREG_STAT_TXEACK | GREG_STAT_TXLERR |
@@ -1609,9 +1609,9 @@
X 		       hp->dev->name, status);
X 
X 	if(status & GREG_STAT_RFIFOVF) {
-		/* The receive FIFO overflowwed, usually a DMA error. */
-		printk("%s: Happy Meal receive FIFO overflow.\n", hp->dev->name);
-		reset = 1;
+		/* Receive FIFO overflow is harmless and the hardware will take
+		   care of it, just some packets are lost. Who cares. */
+		printk(KERN_DEBUG "%s: Happy Meal receive FIFO overflow.\n", hp->dev->name);
X 	}
X 
X 	if(status & GREG_STAT_STSTERR) {
diff -u --recursive --new-file v2.3.3/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.3.3/linux/drivers/sbus/char/Config.in	Sun Oct  4 10:22:44 1998
+++ linux/drivers/sbus/char/Config.in	Mon May 31 22:08:10 1999
@@ -11,4 +11,5 @@
X if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X   tristate 'Bidirectional parallel port support (EXPERIMENTAL)' CONFIG_SUN_BPP
X   tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX
+  tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
X fi
diff -u --recursive --new-file v2.3.3/linux/drivers/sbus/char/Makefile linux/drivers/sbus/char/Makefile
--- v2.3.3/linux/drivers/sbus/char/Makefile	Mon Nov 16 10:37:28 1998
+++ linux/drivers/sbus/char/Makefile	Mon May 31 22:08:10 1999
@@ -87,6 +87,14 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_SUN_AURORA),y)
+O_OBJS += aurora.o
+else
+  ifeq ($(CONFIG_SUN_AURORA),m)
+  M_OBJS += aurora.o
+  endif
+endif
+
X include $(TOPDIR)/Rules.make
X 
X sunkbdmap.o: sunkeymap.c
diff -u --recursive --new-file v2.3.3/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- v2.3.3/linux/drivers/sbus/char/aurora.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sbus/char/aurora.c	Mon May 31 22:08:10 1999
@@ -0,0 +1,2373 @@
+/*
+ *	linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
+ *
+ *	Copyright (c) 1999 by Oliver Aldulea (o...@bv.ro)
+ *
+ *	This code is based on the RISCom/8 multiport serial driver written
+ *	by Dmitry Gorodchanin (pgm...@ibi.com), based on the Linux serial
+ *	driver, written by Linus Torvalds, Theodore T'so and others.
+ *	The Aurora multiport programming info was obtained mainly from the
+ *	Cirrus Logic CD180 documentation (available on the web), and by
+ *	doing heavy tests on the board. Many thanks to Eddie C. Dost for the
+ *	help on the sbus interface.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	Revision 1.0
+ *
+ *	This is the first public release.
+ *
+ *	Most of the information you need is in the aurora.h file. Please
+ *	read that file before reading this one.
+ *
+ *	Several parts of the code do not have comments yet.
+ */
+
+#include <linux/module.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#ifdef AURORA_INT_DEBUG
+#include <linux/timer.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/config.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tqueue.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/oplib.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/kdebug.h>
+#include <asm/sbus.h>
+#include <asm/uaccess.h>
+
+#include "aurora.h"
+#include "cd180.h"
+
+unsigned char irqs[4] = {
+	0, 0, 0, 0
+	};
+
+#ifdef AURORA_INT_DEBUG
+int irqhit=0;
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define AURORA_TYPE_NORMAL	1
+
+static struct tty_driver aurora_driver;
+static struct Aurora_board aurora_board[AURORA_NBOARD] = {
+	{0,},
+};
+
+static struct Aurora_port aurora_port[AURORA_TNPORTS] =  {
+	{ 0, },
+};
+
+/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/
+static unsigned char * tmp_buf = NULL;
+static DECLARE_MUTEX(tmp_buf_sem);
+static int    aurora_refcount = 0;
+static struct tty_struct * aurora_table[AURORA_TNPORTS] = { NULL, };
+static struct termios * aurora_termios[AURORA_TNPORTS] = { NULL, };
+static struct termios * aurora_termios_locked[AURORA_TNPORTS] = { NULL, };
+
+DECLARE_TASK_QUEUE(tq_aurora);
+
+/* Yes, the board can support 115.2 bit rates, but only on a few ports. The
+ * total badwidth of one chip (ports 0-7 or 8-15) is equal to OSC_FREQ div
+ * 16. In case of my board, each chip can take 6 channels of 115.2 kbaud.
+ * This information is not well-tested.
+ */
+static unsigned long baud_table[] =  {
+        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+        9600, 19200, 38400, 57600, 115200, 0,
+        };
+
+static inline int aurora_paranoia_check(struct Aurora_port const * port,
+				    kdev_t device, const char *routine)
+{
+#ifdef AURORA_PARANOIA_CHECK
+	static const char *badmagic =
+		KERN_DEBUG "aurora: Warning: bad aurora port magic number for device %s in %s\n";
+	static const char *badinfo =
+		KERN_DEBUG "aurora: Warning: null aurora port for device %s in %s\n";
+
+	if (!port) {
+		printk(badinfo, kdevname(device), routine);
+		return 1;
+	}
+	if (port->magic != AURORA_MAGIC) {
+		printk(badmagic, kdevname(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * 
+ * Service functions for aurora driver.
+ * 
+ */
+
+/* Get board number from pointer */
+extern inline int board_No (struct Aurora_board const * bp)
+{
+	return bp - aurora_board;
+}
+
+/* Get port number from pointer */
+extern inline int port_No (struct Aurora_port const * port)
+{
+	return AURORA_PORT(port - aurora_port); 
+}
+
+/* Get pointer to board from pointer to port */
+extern inline struct Aurora_board * port_Board(struct Aurora_port const * port)
+{
+	return &aurora_board[AURORA_BOARD(port - aurora_port)];
+}
+
+/* Wait for Channel Command Register ready */
+extern inline void aurora_wait_CCR(struct aurora_reg128 * r)
+{
+	unsigned long delay;
+
+#ifdef AURORA_DEBUG
+printk("aurora_wait_CCR\n");
+#endif
+	/* FIXME: need something more descriptive than 100000 :) */
+	for (delay = 100000; delay; delay--) 
+		if (!r->r[CD180_CCR])
+			return;
+	printk(KERN_DEBUG "aurora: Timeout waiting for CCR.\n");
+}
+
+/*
+ *  aurora probe functions.
+ */
+
+/* Must be called with enabled interrupts */
+extern inline void aurora_long_delay(unsigned long delay)
+{
+	unsigned long i;
+#ifdef AURORA_DEBUG
+printk("aurora_long_delay: start\n");
+#endif
+	for (i = jiffies + delay; i > jiffies; ) ;
+#ifdef AURORA_DEBUG
+printk("aurora_long_delay: end\n");
+#endif
+}
+
+/* Reset and setup CD180 chip */
+static int aurora_init_CD180(struct Aurora_board * bp, int chip)
+{
+	unsigned long flags;
+	int id;
+	
+#ifdef AURORA_DEBUG
+printk("aurora_init_CD180: start %d:%d\n",board_No(bp),chip);
+#endif
+	save_flags(flags); cli();
+	bp->r[chip]->r[CD180_CAR]=0;
+	bp->r[chip]->r[CD180_GSVR]=0;
+	aurora_wait_CCR(bp->r[chip]);			/* Wait for CCR ready        */
+	bp->r[chip]->r[CD180_CCR]=CCR_HARDRESET;      /* Reset CD180 chip          */
+	udelay(1);
+	sti();
+	id=1000;
+	while((--id)&&(bp->r[chip]->r[CD180_GSVR]!=0xff))udelay(100);
+	if(!id) {
+		printk(KERN_ERR "aurora%d: Chip %d failed init.\n",board_No(bp),chip);
+		restore_flags(flags);
+		return(-1);
+		}
+	cli();
+	bp->r[chip]->r[CD180_GSVR]=(board_No(bp)<<5)|((chip+1)<<3); /* Set ID for this chip      */
+	bp->r[chip]->r[CD180_MSMR]=0x80|bp->ACK_MINT;      /* Prio for modem intr       */
+	bp->r[chip]->r[CD180_TSMR]=0x80|bp->ACK_TINT;      /* Prio for transmitter intr */
+	bp->r[chip]->r[CD180_RSMR]=0x80|bp->ACK_RINT;      /* Prio for receiver intr    */
+	/* Setting up prescaler. We need 4 tick per 1 ms */
+	bp->r[chip]->r[CD180_PPRH]=(bp->oscfreq/(1000000/AURORA_TPS)) >> 8;
+	bp->r[chip]->r[CD180_PPRL]=(bp->oscfreq/(1000000/AURORA_TPS)) & 0xff;
+
+	bp->r[chip]->r[CD180_SRCR]=SRCR_AUTOPRI|SRCR_GLOBPRI;
+
+	id=bp->r[chip]->r[CD180_GFRCR];
+	printk(KERN_INFO "aurora%d: Chip %d id %02x: ",board_No(bp),chip,id);
+	if(bp->r[chip]->r[CD180_SRCR]&128)
+		switch(id){
+			case 0x82:printk("CL-CD1864 rev A\n");break;
+			case 0x83:printk("CL-CD1865 rev A\n");break;
+			case 0x84:printk("CL-CD1865 rev B\n");break;
+			case 0x85:printk("CL-CD1865 rev C\n");break;
+			default:printk("Unknown.\n");
+		}else
+		switch(id){
+			case 0x81:printk("CL-CD180 rev B\n");break;
+			case 0x82:printk("CL-CD180 rev C\n");break;
+			default:printk("Unknown.\n");
+		};
+	restore_flags(flags);
+#ifdef AURORA_DEBUG
+printk("aurora_init_CD180: end\n");
+#endif
+	return 0;
+}
+
+static int valid_irq(unsigned char irq)
+{
+int i;
+for(i=0;i<TYPE_1_IRQS;i++)
+	if (type_1_irq[i]==irq) return 1;
+return 0;
+}
+
+static void aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+
+/* Main probing routine, also sets irq. */
+static int aurora_probe(void) {
+	struct linux_sbus *sbus;
+	struct linux_sbus_device *sdev;
+	int grrr;
+	char buf[30];
+	int bn=0;
+	struct Aurora_board *bp;
+
+	for_each_sbus(sbus) {
+		for_each_sbusdev(sdev, sbus) {
+/*			printk("Try: %x %s\n",sdev,sdev->prom_name);*/
+			if (!strcmp(sdev->prom_name, "sio16")) {
+				#ifdef AURORA_DEBUG
+				printk(KERN_INFO "aurora: sio16 at %p\n",sdev);
+				#endif
+				prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev);
+				if((sdev->reg_addrs[0].reg_size!=1)&&(sdev->reg_addrs[1].reg_size!=128)&&
+				   (sdev->reg_addrs[2].reg_size!=128)&&(sdev->reg_addrs[3].reg_size!=4)){
+				   	printk(KERN_ERR "aurora%d: registers' sizes do not match.\n",bn);
+				   	break;
+				   	}
+				bp=&aurora_board[bn];
+				bp->r0 = (struct aurora_reg1 *) sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
+					sdev->reg_addrs[0].reg_size, "sio16",sdev->reg_addrs[0].which_io, 0x0);
+				if (!bp->r0) {
+					printk(KERN_ERR "aurora%d: can't map reg_addrs[0]\n",bn);
+					break;
+				}
+				#ifdef AURORA_DEBUG
+				printk("Map reg 0: %x\n",bp->r0);
+				#endif
+				bp->r[0] = (struct aurora_reg128 *) sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
+					sdev->reg_addrs[1].reg_size, "sio16", sdev->reg_addrs[1].which_io, 0x0);
+				if (!bp->r[0]) {
+					printk(KERN_ERR "aurora%d: can't map reg_addrs[1]\n",bn);
+					break;
+				}
+				#ifdef AURORA_DEBUG
+				printk("Map reg 1: %x\n",bp->r[0]);
+				#endif
+				bp->r[1] = (struct aurora_reg128 *) sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0,
+					sdev->reg_addrs[2].reg_size, "sio16", sdev->reg_addrs[2].which_io, 0x0);
+				if (!bp->r[1]) {
+					printk(KERN_ERR "aurora%d: can't map reg_addrs[2]\n",bn);
+					break;
+				}
+				#ifdef AURORA_DEBUG
+				printk("Map reg 2: %x\n",bp->r[1]);
+				#endif
+				bp->r3 = (struct aurora_reg4 *) sparc_alloc_io(sdev->reg_addrs[3].phys_addr, 0,
+					sdev->reg_addrs[3].reg_size, "sio16", sdev->reg_addrs[3].which_io, 0x0);
+				if (!bp->r3) {
+					printk(KERN_ERR "aurora%d: can't map reg_addrs[3]\n",bn);
+					break;
+				}
+				#ifdef AURORA_DEBUG
+				printk("Map reg 3: %x\n",bp->r3);
+				#endif
+				/* Variables setup */
+				bp->flags = 0;
+				#ifdef AURORA_DEBUG
+				grrr=prom_getint(sdev->prom_node,"intr");
+				printk("intr pri %d\n",grrr);
+				#endif
+				if ((bp->irq=irqs[bn]) && valid_irq(bp->irq) &&
+				    !request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp)) {
+					free_irq(bp->irq|0x30, bp);
+				} else
+				if ((bp->irq=prom_getint(sdev->prom_node, "bintr")) && valid_irq(bp->irq) &&
+				    !request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp)) {
+					free_irq(bp->irq|0x30, bp);
+				} else
+				if ((bp->irq=prom_getint(sdev->prom_node, "intr")) && valid_irq(bp->irq) &&
+				    !request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp)) {
+					free_irq(bp->irq|0x30, bp);
+				} else
+				for(grrr=0;grrr<TYPE_1_IRQS;grrr++) {
+					if ((bp->irq=type_1_irq[grrr])&&!request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp)) {
+						free_irq(bp->irq|0x30, bp);
+						break;
+					} else {
+					printk(KERN_ERR "aurora%d: Could not get an irq for this board !!!\n",bn);
+					bp->flags=0xff;
+					}
+				}
+				if(bp->flags==0xff)break;
+				printk(KERN_INFO "aurora%d: irq %d\n",bn,bp->irq&0x0f);
+				buf[0]=0;
+				grrr=prom_getproperty(sdev->prom_node,"dtr_rts",buf,sizeof(buf));
+				if(!strcmp(buf,"swapped")){
+					printk(KERN_INFO "aurora%d: Swapped DTR and RTS\n",bn);
+					bp->DTR=MSVR_RTS;
+					bp->RTS=MSVR_DTR;
+					bp->MSVDTR=CD180_MSVRTS;
+					bp->MSVRTS=CD180_MSVDTR;
+					bp->flags|=AURORA_BOARD_DTR_FLOW_OK;
+					}else{
+					#ifdef AURORA_FORCE_DTR_FLOW
+					printk(KERN_INFO "aurora%d: Forcing swapped DTR-RTS\n",bn);
+					bp->DTR=MSVR_RTS;
+					bp->RTS=MSVR_DTR;
+					bp->MSVDTR=CD180_MSVRTS;
+					bp->MSVRTS=CD180_MSVDTR;
+					bp->flags|=AURORA_BOARD_DTR_FLOW_OK;
+					#else
+					printk(KERN_INFO "aurora%d: Normal DTR and RTS\n",bn);
+					bp->DTR=MSVR_DTR;
+					bp->RTS=MSVR_RTS;
+					bp->MSVDTR=CD180_MSVDTR;
+					bp->MSVRTS=CD180_MSVRTS;
+					#endif
+				}
+				bp->oscfreq=prom_getint(sdev->prom_node,"clk")*100;
+				printk(KERN_INFO "aurora%d: Oscillator: %d Hz\n",bn,bp->oscfreq);
+				grrr=prom_getproperty(sdev->prom_node,"chip",buf,sizeof(buf));
+				printk(KERN_INFO "aurora%d: Chips: %s\n",bn,buf);
+				grrr=prom_getproperty(sdev->prom_node,"manu",buf,sizeof(buf));
+				printk(KERN_INFO "aurora%d: Manufacturer: %s\n",bn,buf);
+				grrr=prom_getproperty(sdev->prom_node,"model",buf,sizeof(buf));
+				printk(KERN_INFO "aurora%d: Model: %s\n",bn,buf);
+				grrr=prom_getproperty(sdev->prom_node,"rev",buf,sizeof(buf));
+				printk(KERN_INFO "aurora%d: Revision: %s\n",bn,buf);
+				grrr=prom_getproperty(sdev->prom_node,"mode",buf,sizeof(buf));
+				printk(KERN_INFO "aurora%d: Mode: %s\n",bn,buf);
+				#ifdef MODULE
+				bp->count=0;
+				#endif
+				bp->flags = AURORA_BOARD_PRESENT;
+				/* hardware ack */
+				bp->ACK_MINT=1;
+				bp->ACK_TINT=2;
+				bp->ACK_RINT=3;
+				bn++;
+			}
+		}
+	}
+	return bn;
+}
+
+static void aurora_release_io_range(struct Aurora_board *bp)
+{
+sparc_free_io(bp->r0,1);
+sparc_free_io(bp->r[0],128);
+sparc_free_io(bp->r[1],128);
+sparc_free_io(bp->r3,4);
+}
+
+extern inline void aurora_mark_event(struct Aurora_port * port, int event)
+{
+#ifdef AURORA_DEBUG
+printk("aurora_mark_event: start\n");
+#endif
+	set_bit(event, &port->event);
+	queue_task(&port->tqueue, &tq_aurora);
+	mark_bh(AURORA_BH);
+#ifdef AURORA_DEBUG
+printk("aurora_mark_event: end\n");
+#endif
+}
+
+extern inline struct Aurora_port * aurora_get_port(struct Aurora_board const * bp,
+					int chip, unsigned char const * what)
+{
+	unsigned char channel;
+	struct Aurora_port * port;
+
+	channel = (chip<<3)|((bp->r[chip]->r[CD180_GSCR]&GSCR_CHAN)>>GSCR_CHAN_OFF);
+	port = &aurora_port[board_No(bp) * AURORA_NPORT * AURORA_NCD180 + channel];
+	if (port->flags & ASYNC_INITIALIZED)  {
+		return port;
+	}
+	printk(KERN_DEBUG "aurora%d: %s interrupt from invalid port %d\n",
+	       board_No(bp), what, channel);
+	return NULL;
+}
+
+extern inline void aurora_receive_exc(struct Aurora_board const * bp, int chip)
+{
+	struct Aurora_port *port;
+	struct tty_struct *tty;
+	unsigned char status;
+	unsigned char ch;
+	
+	if (!(port = aurora_get_port(bp, chip, "Receive_x")))
+		return;
+
+	tty = port->tty;
+	if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
+	#ifdef AURORA_INTNORM
+		printk("aurora%d: port %d: Working around flip buffer overflow.\n",
+		       board_No(bp), port_No(port));
+	#endif
+		return;
+	}
+	
+#ifdef AURORA_REPORT_OVERRUN	
+	status = bp->r[chip]->r[CD180_RCSR];
+	if (status & RCSR_OE)  {
+		port->overrun++;
+#if 1
+		printk("aurora%d: port %d: Overrun. Total %ld overruns.\n",
+		       board_No(bp), port_No(port), port->overrun);
+#endif		
+	}
+	status &= port->mark_mask;
+#else	
+	status = bp->r[chip]->r[CD180_RCSR] & port->mark_mask;
+#endif	
+	ch = bp->r[chip]->r[CD180_RDR];
+	if (!status)  {
+		return;
+	}
+	if (status & RCSR_TOUT)  {
+/*		printk("aurora%d: port %d: Receiver timeout. Hardware problems ?\n",
+		       board_No(bp), port_No(port));*/
+		return;
+		
+	} else if (status & RCSR_BREAK)  {
+		printk(KERN_DEBUG "aurora%d: port %d: Handling break...\n",
+		       board_No(bp), port_No(port));
+		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+		if (port->flags & ASYNC_SAK)
+			do_SAK(tty);
+		
+	} else if (status & RCSR_PE) 
+		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+	
+	else if (status & RCSR_FE) 
+		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+	
+        else if (status & RCSR_OE)
+		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+	
+	else
+		*tty->flip.flag_buf_ptr++ = 0;
+	
+	*tty->flip.char_buf_ptr++ = ch;
+	tty->flip.count++;
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+extern inline void aurora_receive(struct Aurora_board const * bp, int chip)
+{
+	struct Aurora_port *port;
+	struct tty_struct *tty;
+	unsigned char count,cnt;
+
+	if (!(port = aurora_get_port(bp, chip, "Receive")))
+		return;
+	
+	tty = port->tty;
+	
+	count = bp->r[chip]->r[CD180_RDCR];
+
+#ifdef AURORA_REPORT_FIFO
+	port->hits[count > 8 ? 9 : count]++;
+#endif
+
+	while (count--)  {
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
+		#ifdef AURORA_INTNORM
+			printk("aurora%d: port %d: Working around flip buffer overflow.\n",
+			       board_No(bp), port_No(port));
+		#endif
+			break;
+		}
+		cnt=bp->r[chip]->r[CD180_RDR];
+		*tty->flip.char_buf_ptr++ = cnt;
+		*tty->flip.flag_buf_ptr++ = 0;
+		tty->flip.count++;
+	}
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+extern inline void aurora_transmit(struct Aurora_board const * bp, int chip)
+{
+	struct Aurora_port *port;
+	struct tty_struct *tty;
+	unsigned char count;
+	
+	
+	if (!(port = aurora_get_port(bp, chip, "Transmit")))
+		return;
+		
+	tty = port->tty;
+	
+	if (port->SRER & SRER_TXEMPTY)  {
+		/* FIFO drained */
+		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		udelay(1);
+		port->SRER &= ~SRER_TXEMPTY;
+		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		return;
+	}
+	
+	if ((port->xmit_cnt <= 0 && !port->break_length)
+	    || tty->stopped || tty->hw_stopped)  {
+		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		udelay(1);
+		port->SRER &= ~SRER_TXRDY;
+		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		return;
+	}
+	
+	if (port->break_length)  {
+		if (port->break_length > 0)  {
+			if (port->COR2 & COR2_ETC)  {
+				bp->r[chip]->r[CD180_TDR]=CD180_C_ESC;
+				bp->r[chip]->r[CD180_TDR]=CD180_C_SBRK;
+				port->COR2 &= ~COR2_ETC;
+			}
+			count = MIN(port->break_length, 0xff);
+			bp->r[chip]->r[CD180_TDR]=CD180_C_ESC;
+			bp->r[chip]->r[CD180_TDR]=CD180_C_DELAY;
+			bp->r[chip]->r[CD180_TDR]=count;
+			if (!(port->break_length -= count))
+				port->break_length--;
+		} else  {
+			bp->r[chip]->r[CD180_TDR]=CD180_C_ESC;
+			bp->r[chip]->r[CD180_TDR]=CD180_C_EBRK;
+			bp->r[chip]->r[CD180_COR2]=port->COR2;
+			aurora_wait_CCR(bp->r[chip]);
+			bp->r[chip]->r[CD180_CCR]=CCR_CORCHG2;
+			port->break_length = 0;
+		}
+		return;
+	}
+	
+	count = CD180_NFIFO;
+	do {
+		bp->r[chip]->r[CD180_TDR]=port->xmit_buf[port->xmit_tail++];
+		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
+		if (--port->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+	
+	if (port->xmit_cnt <= 0)  {
+		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		udelay(1);
+		port->SRER &= ~SRER_TXRDY;
+		bp->r[chip]->r[CD180_SRER]=port->SRER;
+	}
+	if (port->xmit_cnt <= port->wakeup_chars)
+		aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
+}
+
+extern inline void aurora_check_modem(struct Aurora_board const * bp, int chip)
+{
+	struct Aurora_port *port;
+	struct tty_struct *tty;
+	unsigned char mcr;
+	
+	if (!(port = aurora_get_port(bp, chip, "Modem")))
+		return;
+		
+	tty = port->tty;
+	
+	mcr = bp->r[chip]->r[CD180_MCR];
+	if (mcr & MCR_CDCHG)  {
+		if (bp->r[chip]->r[CD180_MSVR] & MSVR_CD) 
+			wake_up_interruptible(&port->open_wait);
+		else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (port->flags & ASYNC_CALLOUT_NOHUP)))
+			queue_task(&port->tqueue_hangup,  
+					   &tq_scheduler);      
+	}
+	
+/* We don't have such things yet. My aurora board has DTR and RTS swapped, but that doesn't count in this driver. Let's hope
+ * Aurora didn't made any boards with CTS or DSR broken...
+ */
+/* #ifdef AURORA_BRAIN_DAMAGED_CTS
+	if (mcr & MCR_CTSCHG)  {
+		if (aurora_in(bp, CD180_MSVR) & MSVR_CTS)  {
+			tty->hw_stopped = 0;
+			port->SRER |= SRER_TXRDY;
+			if (port->xmit_cnt <= port->wakeup_chars)
+				aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
+		} else  {
+			tty->hw_stopped = 1;
+			port->SRER &= ~SRER_TXRDY;
+		}
+		bp->r[chip]->r[CD180_SRER, port->SRER);
+	}
+	if (mcr & MCR_DSRCHG)  {
+		if (aurora_in(bp, CD180_MSVR) & MSVR_DSR)  {
+			tty->hw_stopped = 0;
+			port->SRER |= SRER_TXRDY;
+			if (port->xmit_cnt <= port->wakeup_chars)
+				aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
+		} else  {
+			tty->hw_stopped = 1;
+			port->SRER &= ~SRER_TXRDY;
+		}
+		bp->r[chip]->r[CD180_SRER, port->SRER);
+	}
+#endif AURORA_BRAIN_DAMAGED_CTS */
+	
+	/* Clear change bits */
+	bp->r[chip]->r[CD180_MCR]=0;
+}
+
+/* The main interrupt processing routine */
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 32'
echo 'File patch-2.3.4 is continued in part 33'
echo 33 > _shar_seq_.tmp
#!/bin/sh
# this is part 34 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 34; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+
+#define GSVR_ITMASK     0x07     /* Interrupt type mask                     */
+#define  GSVR_IT_MDM     0x01    /* Modem Signal Change Interrupt           */
+#define  GSVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
+#define  GSVR_IT_RGD     0x03    /* Receive Good Data Interrupt             */
+#define  GSVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
+
+
+/* Global Interrupt Channel Register (R/W) */
+ 
+#define GSCR_CHAN       0x1c    /* Channel Number Mask                     */
+#define GSCR_CHAN_OFF   2       /* Channel Number Offset                   */
+
+
+/* Channel Address Register (R/W) */
+
+#define CAR_CHAN        0x07    /* Channel Number Mask                     */
+
+
+/* Receive Character Status Register (R/O) */
+
+#define RCSR_TOUT       0x80    /* Rx Timeout                              */
+#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
+#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
+#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
+#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
+#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
+#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
+#define RCSR_BREAK      0x08    /* Break has been detected                 */
+#define RCSR_PE         0x04    /* Parity Error                            */
+#define RCSR_FE         0x02    /* Frame Error                             */
+#define RCSR_OE         0x01    /* Overrun Error                           */
+
+
+/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
+
+#define CCR_HARDRESET   0x81    /* Reset the chip                          */
+
+#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
+
+#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
+#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
+#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
+
+#define CCR_SSCH1       0x21    /* Send Special Character 1                */
+
+#define CCR_SSCH2       0x22    /* Send Special Character 2                */
+
+#define CCR_SSCH3       0x23    /* Send Special Character 3                */
+
+#define CCR_SSCH4       0x24    /* Send Special Character 4                */
+
+#define CCR_TXEN        0x18    /* Enable Transmitter                      */
+#define CCR_RXEN        0x12    /* Enable Receiver                         */
+
+#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
+#define CCR_RXDIS       0x11    /* Disable Receiver                        */
+
+
+/* Service Request Enable Register (R/W) */
+
+#define SRER_DSR         0x80    /* Enable interrupt on DSR change          */
+#define SRER_CD          0x40    /* Enable interrupt on CD change           */
+#define SRER_CTS         0x20    /* Enable interrupt on CTS change          */
+#define SRER_RXD         0x10    /* Enable interrupt on Receive Data        */
+#define SRER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
+#define SRER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
+#define SRER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
+#define SRER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
+
+
+/* Channel Option Register 1 (R/W) */
+
+#define COR1_ODDP       0x80    /* Odd Parity                              */
+#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
+#define  COR1_NOPAR      0x00   /* No Parity                               */
+#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
+#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
+#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
+#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
+#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
+#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
+#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
+#define COR1_CHARLEN    0x03    /* Character Length                        */
+#define  COR1_5BITS      0x00   /* 5 bits                                  */
+#define  COR1_6BITS      0x01   /* 6 bits                                  */
+#define  COR1_7BITS      0x02   /* 7 bits                                  */
+#define  COR1_8BITS      0x03   /* 8 bits                                  */
+
+
+/* Channel Option Register 2 (R/W) */
+
+#define COR2_IXM        0x80    /* Implied XON mode                        */
+#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
+#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
+#define COR2_LLM        0x10    /* Local Loopback Mode                     */
+#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
+#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
+#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
+#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
+
+
+/* Channel Option Register 3 (R/W) */
+
+#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
+#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
+#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
+#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
+#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
+
+
+/* Channel Control Status Register (R/O) */
+
+#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
+#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
+#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
+#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
+#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
+#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
+
+
+/* Modem Change Option Register 1 (R/W) */
+
+#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
+#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
+#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
+#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
+#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
+
+
+/* Modem Change Option Register 2 (R/W) */
+
+#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
+#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
+#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
+
+
+/* Modem Change Register (R/W) */
+
+#define MCR_DSRCHG      0x80    /* DSR Changed                             */
+#define MCR_CDCHG       0x40    /* CD Changed                              */
+#define MCR_CTSCHG      0x20    /* CTS Changed                             */
+
+
+/* Modem Signal Value Register (R/W) */
+
+#define MSVR_DSR        0x80    /* Current state of DSR input              */
+#define MSVR_CD         0x40    /* Current state of CD input               */
+#define MSVR_CTS        0x20    /* Current state of CTS input              */
+#define MSVR_DTR        0x02    /* Current state of DTR output             */
+#define MSVR_RTS        0x01    /* Current state of RTS output             */
+
+
+/* Service Request Status Register */
+
+#define SRSR_CMASK	0xC0	/* Current Service Context Mask            */
+#define  SRSR_CNONE	0x00	/* Not in a service context		   */
+#define  SRSR_CRX	0x40	/* Rx Context				   */
+#define  SRSR_CTX	0x80	/* Tx Context				   */
+#define  SRSR_CMDM	0xC0	/* Modem Context			   */
+#define SRSR_ANYINT	0x6F	/* Any interrupt flag			   */
+#define SRSR_RINT	0x10	/* Receive Interrupt			   */
+#define SRSR_TINT	0x04	/* Transmit Interrupt			   */
+#define SRSR_MINT	0x01	/* Modem Interrupt			   */
+#define SRSR_REXT	0x20	/* Receive External Interrupt		   */
+#define SRSR_TEXT	0x08	/* Transmit External Interrupt		   */
+#define SRSR_MEXT	0x02	/* Modem External Interrupt		   */
+
+
+/* Service Request Configuration Register */
+
+#define SRCR_PKGTYPE    0x80
+#define SRCR_REGACKEN   0x40
+#define SRCR_DAISYEN    0x20
+#define SRCR_GLOBPRI    0x10
+#define SRCR_UNFAIR     0x08
+#define SRCR_AUTOPRI    0x02
+#define SRCR_PRISEL     0x01
+
+/* Values for register-based Interrupt ACKs */
+#define CD180_ACK_MINT	0x75	/* goes to MSMR				   */
+#define CD180_ACK_TINT	0x76	/* goes to TSMR				   */
+#define CD180_ACK_RINT	0x77	/* goes to RSMR				   */
+
+/* Escape characters */
+
+#define CD180_C_ESC     0x00    /* Escape character                        */
+#define CD180_C_SBRK    0x81    /* Start sending BREAK                     */
+#define CD180_C_DELAY   0x82    /* Delay output                            */
+#define CD180_C_EBRK    0x83    /* Stop sending BREAK                      */
diff -u --recursive --new-file v2.3.3/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.3.3/linux/drivers/sbus/sbus.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/sbus.c	Mon May 31 22:08:10 1999
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.76 1998/12/17 11:11:26 davem Exp $
+/* $Id: sbus.c,v 1.77 1999/05/29 06:25:57 davem Exp $
X  * sbus.c:  SBus support routines.
X  *
X  * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -207,6 +207,9 @@
X #ifdef CONFIG_OBP_FLASH
X extern int flash_init(void);
X #endif
+#ifdef CONFIG_SUN_AURORA
+extern int aurora_init(void);
+#endif
X 
X __initfunc(static void
X sbus_do_child_siblings(int start_node, struct linux_sbus_device *child,
@@ -440,6 +443,9 @@
X #endif
X #ifdef CONFIG_OBP_FLASH
X 	flash_init();
+#endif
+#ifdef CONFIG_SUN_AURORA
+	aurora_init();
X #endif
X #ifdef __sparc_v9__
X 	if (sparc_cpu_model == sun4u) {
diff -u --recursive --new-file v2.3.3/linux/drivers/scsi/README.st linux/drivers/scsi/README.st
--- v2.3.3/linux/drivers/scsi/README.st	Sun Mar  7 15:20:26 1999
+++ linux/drivers/scsi/README.st	Sat May 22 14:50:07 1999
@@ -2,7 +2,7 @@
X The driver is currently maintained by Kai M{kisara (email
X Kai.Ma...@metla.fi)
X 
-Last modified: Sun Jan 17 10:57:41 1999 by makisara@home
+Last modified: Sun Apr 18 13:24:43 1999 by makisara@home
X 
X 
X BASICS
@@ -348,15 +348,6 @@
X 	The GMT_xxx status bits reflect the drive status. GMT_DR_OPEN
X 	is set if there is no tape in the drive. GMT_EOD means either
X 	end of recorded data or end of tape. GMT_EOT means end of tape.
-
-The following ioctls use the structure mtlocation that contains both
-the block number and the partition number. These ioctls are available
-only for SCSI-2 tape drives and the block number is the
-device-independent logical block number defined by the standard.
-
-MTGETLOC Returns the current block and partition number.
-MTSETLOC Sets the tape to the block and partition specified by the
-	arguments.
X 
X 
X MISCELLANEOUS COMPILE OPTIONS
diff -u --recursive --new-file v2.3.3/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.3/linux/drivers/scsi/scsi.c	Fri May 14 18:55:22 1999
+++ linux/drivers/scsi/scsi.c	Wed May 26 09:33:40 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.
@@ -273,6 +274,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},
@@ -936,6 +938,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.3.3/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.3.3/linux/drivers/scsi/st.c	Fri May 14 18:55:22 1999
+++ linux/drivers/scsi/st.c	Sat May 22 14:50:22 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 08:32:34 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.3.3/linux/drivers/scsi/st.h linux/drivers/scsi/st.h
--- v2.3.3/linux/drivers/scsi/st.h	Mon May 17 09:55:22 1999
+++ linux/drivers/scsi/st.h	Sat May 22 14:50:07 1999
@@ -65,7 +65,6 @@
X typedef struct {
X   kdev_t devt;
X   unsigned capacity;
-  wait_queue_head_t waiting;
X   Scsi_Device* device;
X   struct semaphore sem;
X   ST_buffer * buffer;
diff -u --recursive --new-file v2.3.3/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.3.3/linux/drivers/sound/Config.in	Sun Mar  7 15:22:06 1999
+++ linux/drivers/sound/Config.in	Wed May 26 09:35:00 1999
@@ -9,6 +9,7 @@
X 
X # Prompt user for primary drivers.
X 
+dep_tristate 'C-Media PCI (CMI8338/8378)' CONFIG_SOUND_CMPCI $CONFIG_SOUND
X dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
X if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
X    bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
diff -u --recursive --new-file v2.3.3/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.3.3/linux/drivers/sound/Makefile	Thu Jan 14 22:59:47 1999
+++ linux/drivers/sound/Makefile	Wed May 26 09:35:00 1999
@@ -76,6 +76,7 @@
X obj-$(CONFIG_SOUND_WAVEFRONT)   += wavefront.o
X 
X #jnx
+obj-$(CONFIG_SOUND_CMPCI)	+= cmpci.o
X obj-$(CONFIG_SOUND_ES1370)	+= es1370.o
X obj-$(CONFIG_SOUND_ES1371)	+= es1371.o
X obj-$(CONFIG_SOUND_SONICVIBES)	+= sonicvibes.o
diff -u --recursive --new-file v2.3.3/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.3/linux/drivers/sound/cmpci.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cmpci.c	Wed May 26 09:35:00 1999
@@ -0,0 +1,2391 @@
+/*****************************************************************************/
+
+/*
+ *      cmpci.c  --  C-Media PCI audio driver.
+ *
+ *      Copyright (C) 1999  ChenLi Tien (clt...@home.com)
+ *
+ *	Based on the PCI drivers by Thomas Sailer (sai...@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Special thanks to David C. Niemi
+ *
+ *
+ * Module command line parameters:
+ *   none so far
+ *
+ *
+ *  Supported devices:
+ *  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible
+ *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
+ *  /dev/midi   simple MIDI UART interface, no ioctl
+ *
+ *  The card has both an FM and a Wavetable synth, but I have to figure
+ *  out first how to drive them...
+ *
+ *  Revision history
+ *    06.05.98   0.1   Initial release
+ *    10.05.98   0.2   Fixed many bugs, esp. ADC rate calculation
+ *                     First stab at a simple midi interface (no bells&whistles)
+ *    13.05.98   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
+ *                     set_dac_rate in the FMODE_WRITE case in cm_open
+ *                     Fix hwptr out of bounds (now mpg123 works)
+ *    14.05.98   0.4   Don't allow excessive interrupt rates
+ *    08.06.98   0.5   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.98   0.6   Do not include modversions.h
+ *                     Now mixer behaviour can basically be selected between
+ *                     "OSS documented" and "OSS actual" behaviour
+ *    31.08.98   0.7   Fix realplayer problems - dac.count issues
+ *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.98   0.9   Fix a few f_file & FMODE_ bugs
+ *    06.01.99   0.10  remove the silly SA_INTERRUPT flag.
+ *                     hopefully killed the egcs section type conflict
+ *    12.03.99   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                     reported by Johan Maes <jo...@telindus.be>
+ *    22.03.99   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                     read/write cannot be executed
+ *
+ */
+
+/*****************************************************************************/
+      
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/malloc.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <asm/spinlock.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+
+#include "dm.h"
+
+/* --------------------------------------------------------------------- */
+
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
+#ifndef PCI_VENDOR_ID_CMEDIA
+#define PCI_VENDOR_ID_CMEDIA         0x13F6
+#endif
+#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A
+#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
+#endif
+#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B
+#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
+#endif
+#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
+#define PCI_DEVICE_ID_CMEDIA_CM8738  0x0111
+#endif
+
+#define CM_MAGIC  ((PCI_VENDOR_ID_CMEDIA<<16)|PCI_DEVICE_ID_CMEDIA_CM8338A)
+
+/*
+ * CM8338 registers definition
+ */
+
+#define CODEC_CMI_FUNCTRL0      (0x00)
+#define CODEC_CMI_FUNCTRL1      (0x04)
+#define CODEC_CMI_CHFORMAT      (0x08)
+#define CODEC_CMI_INT_HLDCLR    (0x0C)
+#define CODEC_CMI_INT_STATUS    (0x10)
+#define CODEC_CMI_LEGACY_CTRL   (0x14)
+#define CODEC_CMI_MISC_CTRL     (0x18)
+#define CODEC_CMI_TDMA_POS      (0x1C)
+#define CODEC_CMI_MIXER         (0x20)
+#define CODEC_SB16_DATA         (0x22)
+#define CODEC_SB16_ADDR         (0x23)
+#define CODEC_CMI_MIXER1        (0x24)
+#define CODEC_CMI_MIXER2        (0x25)
+#define CODEC_CMI_AUX_VOL       (0x26)
+#define CODEC_CMI_MISC          (0x27)
+#define CODEC_CMI_AC97          (0x28)
+
+#define CODEC_CMI_CH0_FRAME1    (0x80)
+#define CODEC_CMI_CH0_FRAME2    (0x84)
+#define CODEC_CMI_CH1_FRAME1    (0x88)
+#define CODEC_CMI_CH1_FRAME2    (0x8C)
+
+#define CODEC_CMI_EXT_REG       (0xF0)
+#define UCHAR	unsigned char
+/*
+**  Mixer registers for SB16
+*/
+
+#define DSP_MIX_DATARESETIDX    ((UCHAR)(0x00))
+
+#define DSP_MIX_MASTERVOLIDX_L  ((UCHAR)(0x30))
+#define DSP_MIX_MASTERVOLIDX_R  ((UCHAR)(0x31))
+#define DSP_MIX_VOICEVOLIDX_L   ((UCHAR)(0x32))
+#define DSP_MIX_VOICEVOLIDX_R   ((UCHAR)(0x33))
+#define DSP_MIX_FMVOLIDX_L      ((UCHAR)(0x34))
+#define DSP_MIX_FMVOLIDX_R      ((UCHAR)(0x35))
+#define DSP_MIX_CDVOLIDX_L      ((UCHAR)(0x36))
+#define DSP_MIX_CDVOLIDX_R      ((UCHAR)(0x37))
+#define DSP_MIX_LINEVOLIDX_L    ((UCHAR)(0x38))
+#define DSP_MIX_LINEVOLIDX_R    ((UCHAR)(0x39))
+
+#define DSP_MIX_MICVOLIDX       ((UCHAR)(0x3A))
+#define DSP_MIX_SPKRVOLIDX      ((UCHAR)(0x3B))
+
+#define DSP_MIX_OUTMIXIDX       ((UCHAR)(0x3C))
+
+#define DSP_MIX_ADCMIXIDX_L     ((UCHAR)(0x3D))
+#define DSP_MIX_ADCMIXIDX_R     ((UCHAR)(0x3E))
+
+#define DSP_MIX_INGAINIDX_L     ((UCHAR)(0x3F))
+#define DSP_MIX_INGAINIDX_R     ((UCHAR)(0x40))
+#define DSP_MIX_OUTGAINIDX_L    ((UCHAR)(0x41))
+#define DSP_MIX_OUTGAINIDX_R    ((UCHAR)(0x42))
+
+#define DSP_MIX_AGCIDX          ((UCHAR)(0x43))
+
+#define DSP_MIX_TREBLEIDX_L     ((UCHAR)(0x44))
+#define DSP_MIX_TREBLEIDX_R     ((UCHAR)(0x45))
+#define DSP_MIX_BASSIDX_L       ((UCHAR)(0x46))
+#define DSP_MIX_BASSIDX_R       ((UCHAR)(0x47))
+#define CM_CH0_RESET	  0x04
+#define CM_CH1_RESET	  0x08
+#define CM_EXTENT_CODEC	  0x100
+#define CM_EXTENT_MIDI	  0x2
+#define CM_EXTENT_SYNTH	  0x4
+#define CM_INT_CH0	  1
+#define CM_INT_CH1	  2
+
+#define CM_CFMT_STEREO     0x01
+#define CM_CFMT_16BIT      0x02
+#define CM_CFMT_MASK       0x03
+#define CM_CFMT_DACSHIFT   0   
+#define CM_CFMT_ADCSHIFT   2
+
+static const unsigned sample_size[] = { 1, 2, 2, 4 };
+static const unsigned sample_shift[] = { 0, 1, 1, 2 };
+
+#define CM_CENABLE_RE      0x2
+#define CM_CENABLE_PE      0x1
+
+
+/* MIDI buffer sizes */
+
+#define MIDIINBUF  256
+#define MIDIOUTBUF 256
+
+#define FMODE_MIDI_SHIFT 2
+#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
+#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
+
+#define FMODE_DMFM 0x10
+
+#define SND_DEV_DSP16   5 
+
+/* --------------------------------------------------------------------- */
+
+struct cm_state {
+	/* magic */
+	unsigned int magic;
+
+	/* we keep cm cards in a linked list */
+	struct cm_state *next;
+
+	/* soundcore stuff */
+	int dev_audio;
+	int dev_mixer;
+	int dev_midi;
+	int dev_dmfm;
+
+	/* hardware resources */
+	unsigned int iosb, iobase, iosynth, iomidi, iogame, irq;
+
+        /* mixer stuff */
+        struct {
+                unsigned int modcnt;
+#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
+		unsigned short vol[13];
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+        } mix;
+
+	/* wave stuff */
+	unsigned int rateadc, ratedac;
+	unsigned char fmt, enable;
+
+	spinlock_t lock;
+	struct semaphore open_sem;
+	mode_t open_mode;
+	wait_queue_head_t open_wait;
+
+	struct dmabuf {
+		void *rawbuf;
+		unsigned buforder;
+		unsigned numfrag;
+		unsigned fragshift;
+		unsigned hwptr, swptr;
+		unsigned total_bytes;
+		int count;
+		unsigned error; /* over/underrun */
+		wait_queue_head_t wait;
+		/* redundant, but makes calculations easier */
+		unsigned fragsize;
+		unsigned dmasize;
+		unsigned fragsamples;
+		/* OSS stuff */
+		unsigned mapped:1;
+		unsigned ready:1;
+		unsigned endcleared:1;
+		unsigned ossfragshift;
+		int ossmaxfrags;
+		unsigned subdivision;
+	} dma_dac, dma_adc;
+
+	/* midi stuff */
+	struct {
+		unsigned ird, iwr, icnt;
+		unsigned ord, owr, ocnt;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
+		struct timer_list timer;
+		unsigned char ibuf[MIDIINBUF];
+		unsigned char obuf[MIDIOUTBUF];
+	} midi;
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct cm_state *devs = NULL;
+static unsigned long wavetable_mem = 0;
+
+/* --------------------------------------------------------------------- */
+
+extern __inline__ unsigned ld2(unsigned int x)
+{
+	unsigned r = 0;
+	
+	if (x >= 0x10000) {
+		x >>= 16;
+		r += 16;
+	}
+	if (x >= 0x100) {
+		x >>= 8;
+		r += 8;
+	}
+	if (x >= 0x10) {
+		x >>= 4;
+		r += 4;
+	}
+	if (x >= 4) {
+		x >>= 2;
+		r += 2;
+	}
+	if (x >= 2)
+		r++;
+	return r;
+}
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#ifdef hweight32
+#undef hweight32
+#endif
+
+extern __inline__ unsigned int hweight32(unsigned int w)
+{
+        unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+        res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+        res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+        res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+        return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+/* --------------------------------------------------------------------- */
+
+static void set_dmadac(struct cm_state *s, unsigned int addr, unsigned int count)
+{
+	count--;
+	outl(addr, s->iobase + CODEC_CMI_CH0_FRAME1);
+	outw(count, s->iobase + CODEC_CMI_CH0_FRAME2);
+	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0) & ~1, s->iobase + CODEC_CMI_FUNCTRL0);
+	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 1, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+}
+
+static void set_dmaadc(struct cm_state *s, unsigned int addr, unsigned int count)
+{
+	count--;
+	outl(addr, s->iobase + CODEC_CMI_CH1_FRAME1);
+	outw(count, s->iobase + CODEC_CMI_CH1_FRAME2);
+	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0) | 2, s->iobase + CODEC_CMI_FUNCTRL0);
+	outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 2, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+}
+
+extern __inline__ unsigned get_dmadac(struct cm_state *s)
+{
+	unsigned int curr_addr;
+
+	curr_addr = inl(s->iobase + CODEC_CMI_CH0_FRAME1);
+	curr_addr -= virt_to_bus(s->dma_dac.rawbuf);
+	curr_addr = s->dma_dac.dmasize - curr_addr;
+	curr_addr &= ~(sample_size[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]-1);
+	return curr_addr;
+}
+
+extern __inline__ unsigned get_dmaadc(struct cm_state *s)
+{
+	unsigned int curr_addr;
+
+	curr_addr = inl(s->iobase + CODEC_CMI_CH1_FRAME1);
+	curr_addr -= virt_to_bus(s->dma_adc.rawbuf);
+	curr_addr = s->dma_adc.dmasize - curr_addr;
+	curr_addr &= ~(sample_size[(s->fmt >> CM_CFMT_ADCSHIFT) & CM_CFMT_MASK]-1);
+	return curr_addr;
+}
+
+static void wrmixer(struct cm_state *s, unsigned char idx, unsigned char data)
+{
+	outb(idx, s->iobase + CODEC_SB16_ADDR);
+	udelay(10);
+	outb(data, s->iobase + CODEC_SB16_DATA);
+	udelay(10);
+}
+
+static unsigned char rdmixer(struct cm_state *s, unsigned char idx)
+{
+	unsigned char v;
+
+	outb(idx, s->iobase + CODEC_SB16_ADDR);
+	udelay(10);
+	v = inb(s->iobase + CODEC_SB16_DATA);
+	udelay(10);
+	return v;
+}
+
+static void set_fmt(struct cm_state *s, unsigned char mask, unsigned char data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if (mask) {
+		s->fmt = inb(s->iobase + CODEC_CMI_CHFORMAT);
+		udelay(10);
+	}
+	s->fmt = (s->fmt & mask) | data;
+	outb(s->fmt, s->iobase + CODEC_CMI_CHFORMAT);
+	spin_unlock_irqrestore(&s->lock, flags);
+	udelay(10);
+}
+
+static void frobindir(struct cm_state *s, unsigned char idx, unsigned char mask, unsigned char data)
+{
+	outb(idx, s->iobase + CODEC_SB16_ADDR);
+	udelay(10);
+	outb((inb(s->iobase + CODEC_SB16_DATA) & mask) | data, s->iobase + CODEC_SB16_DATA);
+	udelay(10);
+}
+
+static struct {
+	unsigned	rate;
+	unsigned	lower;
+	unsigned	upper;
+	unsigned char	freq;
+} rate_lookup[] =
+{
+	{ 5512,		(0 + 5512) / 2,		(5512 + 8000) / 2,	0 },
+	{ 8000,		(5512 + 8000) / 2,	(8000 + 11025) / 2,	4 },
+	{ 11025,	(8000 + 11025) / 2,	(11025 + 16000) / 2,	1 },
+	{ 16000,	(11025 + 16000) / 2,	(16000 + 22050) / 2,	5 },
+	{ 22050,	(16000 + 22050) / 2,	(22050 + 32000) / 2,	2 },
+	{ 32000,	(22050 + 32000) / 2,	(32000 + 44100) / 2,	6 },
+	{ 44100,	(32000 + 44100) / 2,	(44100 + 48000) / 2,	3 },
+	{ 48000,	48000,			48000,			7 }
+};
+
+static void set_dac_rate(struct cm_state *s, unsigned rate)
+{
+	unsigned long flags;
+	unsigned char freq = 4, val;
+	int	i;
+
+	if (rate > 48000)
+		rate = 48000;
+	if (rate < 5512)
+		rate = 5512;
+	for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++)
+	{
+		if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper)
+		{
+			rate = rate_lookup[i].rate;
+			freq = rate_lookup[i].freq;
+			break;
+	    	}
+	}
+	s->ratedac = rate;
+	freq <<= 2;
+	spin_lock_irqsave(&s->lock, flags);
+	val = inb(s->iobase + CODEC_CMI_FUNCTRL1 + 1) & ~0x1c; 
+	outb(val | freq, s->iobase + CODEC_CMI_FUNCTRL1 + 1);
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void set_adc_rate(struct cm_state *s, unsigned rate)
+{
+	unsigned long flags;
+	unsigned char freq = 4, val;
+	int	i;
+
+	if (rate > 48000)
+		rate = 48000;
+	if (rate < 5512)
+		rate = 5512;
+	for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++)
+	{
+		if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper)
+		{
+			rate = rate_lookup[i].rate;
+			freq = rate_lookup[i].freq;
+			break;
+	    	}
+	}
+	s->rateadc = rate;
+	freq <<= 5;
+	spin_lock_irqsave(&s->lock, flags);
+	val = inb(s->iobase + CODEC_CMI_FUNCTRL1 + 1) & ~0xe0; 
+	outb(val | freq, s->iobase + CODEC_CMI_FUNCTRL1 + 1);
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+/* --------------------------------------------------------------------- */
+
+extern inline void stop_adc(struct cm_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	s->enable &= ~CM_CENABLE_RE;
+	/* disable interrupt */
+	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) & ~2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	/* disable channel and reset */
+	outb(s->enable | CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	udelay(10);
+	outb(s->enable & ~CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+extern inline void stop_dac(struct cm_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	s->enable &= ~CM_CENABLE_PE;
+	/* disable interrupt */
+	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) & ~1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	/* disable channel and reset */
+	outb(s->enable | CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	udelay(10);
+	outb(s->enable & ~CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+static void start_dac(struct cm_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
+		s->enable |= CM_CENABLE_PE;
+		outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	}
+	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+static void start_adc(struct cm_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) 
+	    && s->dma_adc.ready) {
+		s->enable |= CM_CENABLE_RE;
+		outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	}
+	outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+/* --------------------------------------------------------------------- */
+
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
+#define DMABUF_MINORDER 1
+
+static void dealloc_dmabuf(struct dmabuf *db)
+{
+	unsigned long map, mapend;
+
+	if (db->rawbuf) {
+		/* undo marking the pages as reserved */
+		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+			clear_bit(PG_reserved, &mem_map[map].flags);	
+		free_pages((unsigned long)db->rawbuf, db->buforder);
+	}
+	db->rawbuf = NULL;
+	db->mapped = db->ready = 0;
+}
+
+
+/* Ch0 is used for playback, Ch1 is used for recording */
+
+static int prog_dmabuf(struct cm_state *s, unsigned rec)
+{
+	struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac;
+	unsigned rate = rec ? s->rateadc : s->ratedac;
+	int order;
+	unsigned bytepersec;
+	unsigned bufs;
+	unsigned long map, mapend;
+	unsigned char fmt;
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	fmt = s->fmt;
+	if (rec) {
+		s->enable &= ~CM_CENABLE_RE;
+		fmt >>= CM_CFMT_ADCSHIFT;
+	} else {
+		s->enable &= ~CM_CENABLE_PE;
+		fmt >>= CM_CFMT_DACSHIFT;
+	}
+	outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+	spin_unlock_irqrestore(&s->lock, flags);
+	fmt &= CM_CFMT_MASK;
+	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
+	if (!db->rawbuf) {
+		db->ready = db->mapped = 0;
+		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--)
+			db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
+		if (!db->rawbuf)
+			return -ENOMEM;
+		db->buforder = order;
+		if ((virt_to_bus(db->rawbuf) ^ (virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff)
+			printk(KERN_DEBUG "cm: DMA buffer crosses 64k boundary: busaddr 0x%lx  size %ld\n", 
+			       virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder);
+		if ((virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff)
+			printk(KERN_DEBUG "cm: DMA buffer beyond 16MB: busaddr 0x%lx  size %ld\n", 
+			       virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder);
+		/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+			set_bit(PG_reserved, &mem_map[map].flags);
+	}
+	bytepersec = rate << sample_shift[fmt];
+	bufs = PAGE_SIZE << db->buforder;
+	if (db->ossfragshift) {
+		if ((1000 << db->ossfragshift) < bytepersec)
+			db->fragshift = ld2(bytepersec/1000);
+		else
+			db->fragshift = db->ossfragshift;
+	} else {
+		db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
+		if (db->fragshift < 3)
+			db->fragshift = 3;
+	}
+	db->numfrag = bufs >> db->fragshift;
+	while (db->numfrag < 4 && db->fragshift > 3) {
+		db->fragshift--;
+		db->numfrag = bufs >> db->fragshift;
+	}
+	db->fragsize = 1 << db->fragshift;
+	if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
+		db->numfrag = db->ossmaxfrags;
+#if 1
+	/* to make fragsize >= 4096 */
+	while (db->fragsize < 4096 && db->numfrag >= 4)
+	{
+		db->fragsize *= 2;
+		db->fragshift++;
+		db->numfrag /= 2;
+	}
+#endif
+	db->fragsamples = db->fragsize >> sample_shift[fmt];
+	db->dmasize = db->numfrag << db->fragshift;
+	memset(db->rawbuf, (fmt & CM_CFMT_16BIT) ? 0 : 0x80, db->dmasize);
+	spin_lock_irqsave(&s->lock, flags);
+	if (rec) {
+		set_dmaadc(s, virt_to_bus(db->rawbuf), db->dmasize >> sample_shift[fmt]);
+		/* program sample counts */
+		outw(db->fragsamples-1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2);
+	} else {
+		set_dmadac(s, virt_to_bus(db->rawbuf), db->dmasize >> sample_shift[fmt]);
+		/* program sample counts */
+		outw(db->fragsamples-1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2);
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	db->ready = 1;
+	return 0;
+}
+
+extern __inline__ void clear_advance(struct cm_state *s)
+{
+	unsigned char c = (s->fmt & (CM_CFMT_16BIT << CM_CFMT_DACSHIFT)) ? 0 : 0x80;
+	unsigned char *buf = s->dma_dac.rawbuf;
+	unsigned bsize = s->dma_dac.dmasize;
+	unsigned bptr = s->dma_dac.swptr;
+	unsigned len = s->dma_dac.fragsize;
+
+	if (bptr + len > bsize) {
+		unsigned x = bsize - bptr;
+		memset(buf + bptr, c, x);
+		bptr = 0;
+		len -= x;
+	}
+	memset(buf + bptr, c, len);
+}
+
+/* call with spinlock held! */
+static void cm_update_ptr(struct cm_state *s)
+{
+	unsigned hwptr;
+	int diff;
+
+	/* update ADC pointer */
+	if (s->dma_adc.ready) {
+		hwptr = (s->dma_adc.dmasize - get_dmaadc(s)) % s->dma_adc.dmasize;
+		diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
+		s->dma_adc.hwptr = hwptr;
+		s->dma_adc.total_bytes += diff;
+		s->dma_adc.count += diff;
+		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) 
+			wake_up(&s->dma_adc.wait);
+		if (!s->dma_adc.mapped) {
+			if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
+				s->enable &= ~CM_CENABLE_RE;
+				outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+				s->dma_adc.error++;
+			}
+		}
+	}
+	/* update DAC pointer */
+	if (s->dma_dac.ready) {
+		hwptr = (s->dma_dac.dmasize - get_dmadac(s)) % s->dma_dac.dmasize;
+		diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
+		s->dma_dac.hwptr = hwptr;
+		s->dma_dac.total_bytes += diff;
+		if (s->dma_dac.mapped) {
+			s->dma_dac.count += diff;
+			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
+				wake_up(&s->dma_dac.wait);
+		} else {
+			s->dma_dac.count -= diff;
+			if (s->dma_dac.count <= 0) {
+				s->enable &= ~CM_CENABLE_PE;
+				outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
+				s->dma_dac.error++;
+			} else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
+				clear_advance(s);
+				s->dma_dac.endcleared = 1;
+			}
+			if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize)
+				wake_up(&s->dma_dac.wait);
+		}
+	}
+}
+
+/* hold spinlock for the following! */
+static void cm_handle_midi(struct cm_state *s)
+{
+	unsigned char ch;
+	int wake;
+
+	wake = 0;
+	while (!(inb(s->iomidi+1) & 0x80)) {
+		ch = inb(s->iomidi);
+		if (s->midi.icnt < MIDIINBUF) {
+			s->midi.ibuf[s->midi.iwr] = ch;
+			s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
+			s->midi.icnt++;
+		}
+		wake = 1;
+	}
+	if (wake)
+		wake_up(&s->midi.iwait);
+	wake = 0;
+	while (!(inb(s->iomidi+1) & 0x40) && s->midi.ocnt > 0) {
+		outb(s->midi.obuf[s->midi.ord], s->iomidi);
+		s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
+		s->midi.ocnt--;
+		if (s->midi.ocnt < MIDIOUTBUF-16)
+			wake = 1;
+	}
+	if (wake)
+		wake_up(&s->midi.owait);
+}
+
+static void cm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+        struct cm_state *s = (struct cm_state *)dev_id;
+	unsigned int intsrc, intstat;
+	
+	/* fastpath out, to ease interrupt sharing */
+	intsrc = inb(s->iobase + CODEC_CMI_INT_STATUS);
+	if (!(intsrc & (CM_INT_CH0 | CM_INT_CH1)))
+		return;
+	spin_lock(&s->lock);
+	intstat = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	/* disable interrupt */
+	if (intsrc & CM_INT_CH0)
+		outb(intstat & ~1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	if (intsrc & CM_INT_CH1)
+		outb(intstat & ~2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	cm_update_ptr(s);
+#ifdef SOUND_CONFIG_CMPCI_MIDI
+	cm_handle_midi(s);
+#endif
+	/* enable interrupt */
+	if (intsrc & CM_INT_CH0)
+		outb(intstat | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	if (intsrc & CM_INT_CH1)
+		outb(intstat | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
+	spin_unlock(&s->lock);
+}
+
+static void cm_midi_timer(unsigned long data)
+{
+	struct cm_state *s = (struct cm_state *)data;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&s->lock, flags);
+	cm_handle_midi(s);
+	spin_unlock_irqrestore(&s->lock, flags);
+	s->midi.timer.expires = jiffies+1;
+	add_timer(&s->midi.timer);
+}
+
+/* --------------------------------------------------------------------- */
+
+static const char invalid_magic[] = KERN_CRIT "cm: invalid magic value\n";
+
+#ifdef CONFIG_SOUND_CMPCI	/* support multiple chips */
+#define VALIDATE_STATE(s)
+#else
+#define VALIDATE_STATE(s)                         \
+({                                                \
+	if (!(s) || (s)->magic != CM_MAGIC) { \
+		printk(invalid_magic);            \
+		return -ENXIO;                    \
+	}                                         \
+})
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#define MT_4          1
+#define MT_5MUTE      2
+#define MT_4MUTEMONO  3
+#define MT_6MUTE      4
+
+static const struct {
+	unsigned left;
+	unsigned right;
+	unsigned type;
+	unsigned rec;
+	unsigned play;
+} mixtable[SOUND_MIXER_NRDEVICES] = {
+	[SOUND_MIXER_CD]     = { DSP_MIX_CDVOLIDX_L,     DSP_MIX_CDVOLIDX_R,     MT_5MUTE,     0x04, 0x02 },
+	[SOUND_MIXER_LINE]   = { DSP_MIX_LINEVOLIDX_L,   DSP_MIX_LINEVOLIDX_R,   MT_5MUTE,     0x10, 0x08 },
+	[SOUND_MIXER_MIC]    = { DSP_MIX_MICVOLIDX,      CODEC_CMI_MIXER2,       MT_4MUTEMONO, 0x01, 0x01 },
+	[SOUND_MIXER_SYNTH]  = { DSP_MIX_FMVOLIDX_L,  	 DSP_MIX_FMVOLIDX_R,     MT_5MUTE,     0x40, 0x00 },
+	[SOUND_MIXER_VOLUME] = { DSP_MIX_MASTERVOLIDX_L, DSP_MIX_MASTERVOLIDX_R, MT_5MUTE,     0x00, 0x00 },
+	[SOUND_MIXER_PCM]    = { DSP_MIX_VOICEVOLIDX_L,  DSP_MIX_VOICEVOLIDX_R,  MT_5MUTE,     0x00, 0x00 }
+};
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+static int return_mixval(struct cm_state *s, unsigned i, int *arg)
+{
+	unsigned long flags;
+	unsigned char l, r, rl, rr;
+
+	spin_lock_irqsave(&s->lock, flags);
+	l = rdmixer(s, mixtable[i].left);
+	r = rdmixer(s, mixtable[i].right);
+	spin_unlock_irqrestore(&s->lock, flags);
+	switch (mixtable[i].type) {
+	case MT_4:
+		r &= 0xf;
+		l &= 0xf;
+		rl = 10 + 6 * (l & 15);
+		rr = 10 + 6 * (r & 15);
+		break;
+
+	case MT_4MUTEMONO:
+		rl = 55 - 3 * (l & 15);
+		if (r & 0x10)
+			rl += 45;
+		rr = rl;
+		r = l;
+		break;
+
+	case MT_5MUTE:
+	default:
+		rl = 100 - 3 * (l & 31);
+		rr = 100 - 3 * (r & 31);
+		break;
+				
+	case MT_6MUTE:
+		rl = 100 - 3 * (l & 63) / 2;
+		rr = 100 - 3 * (r & 63) / 2;
+		break;
+	}
+	if (l & 0x80)
+		rl = 0;
+	if (r & 0x80)
+		rr = 0;
+	return put_user((rr << 8) | rl, arg);
+}
+
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
+static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = 
+{
+	[SOUND_MIXER_CD]     = 1,
+	[SOUND_MIXER_LINE]   = 2,
+	[SOUND_MIXER_MIC]    = 3,
+	[SOUND_MIXER_SYNTH]  = 4,
+	[SOUND_MIXER_VOLUME] = 5,
+	[SOUND_MIXER_PCM]    = 6
+};
+
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
+static unsigned mixer_recmask(struct cm_state *s)
+{
+	unsigned long flags;
+	int i, j, k;
+
+	spin_lock_irqsave(&s->lock, flags);
+	j = rdmixer(s, DSP_MIX_ADCMIXIDX_L);
+	spin_unlock_irqrestore(&s->lock, flags);
+	j &= 0x7f;
+	for (k = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+		if (j & mixtable[i].rec)
+			k |= 1 << i;
+	return k;
+}
+
+static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	int i, val, j;
+	unsigned char l, r, rl, rr;
+
+	VALIDATE_STATE(s);
+        if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		strncpy(info.id, "cmpci", sizeof(info.id));
+		strncpy(info.name, "C-Media PCI", sizeof(info.name));
+		info.modify_counter = s->mix.modcnt;
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == SOUND_OLD_MIXER_INFO) {
+		_old_mixer_info info;
+		strncpy(info.id, "cmpci", sizeof(info.id));
+		strncpy(info.name, "C-Media cmpci", sizeof(info.name));
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *)arg);
+	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+                return -EINVAL;
+        if (_IOC_DIR(cmd) == _IOC_READ) {
+                switch (_IOC_NR(cmd)) {
+                case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+			return put_user(mixer_recmask(s), (int *)arg);
+			
+                case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */
+			return put_user(mixer_recmask(s), (int *)arg);//need fix
+			
+                case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
+			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+				if (mixtable[i].type)
+					val |= 1 << i;
+			return put_user(val, (int *)arg);
+
+                case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
+			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+				if (mixtable[i].rec)
+					val |= 1 << i;
+			return put_user(val, (int *)arg);
+			
+                case SOUND_MIXER_OUTMASK: /* Arg contains a bit for each supported recording source */
+			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+				if (mixtable[i].play)
+					val |= 1 << i;
+			return put_user(val, (int *)arg);
+			
+                 case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
+			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+				if (mixtable[i].type && mixtable[i].type != MT_4MUTEMONO)
+					val |= 1 << i;
+			return put_user(val, (int *)arg);
+			
+                case SOUND_MIXER_CAPS:
+			return put_user(0, (int *)arg);
+
+		default:
+			i = _IOC_NR(cmd);
+                        if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
+                                return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+			return return_mixval(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+			if (!volidx[i])
+				return -EINVAL;
+			return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+		}
+	}
+        if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
+		return -EINVAL;
+	s->mix.modcnt++;
+	switch (_IOC_NR(cmd)) {
+	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+		get_user_ret(val, (int *)arg, -EFAULT);
+		i = hweight32(val);
+		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+			if (!(val & (1 << i)))
+				continue;
+			if (!mixtable[i].rec) {
+				val &= ~(1 << i);
+				continue;
+			}
+			j |= mixtable[i].rec;
+		}
+		spin_lock_irqsave(&s->lock, flags);
+		wrmixer(s, DSP_MIX_ADCMIXIDX_L, j);
+		wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | j>>1);
+		spin_unlock_irqrestore(&s->lock, flags);
+		return 0;
+
+	case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */
+		get_user_ret(val, (int *)arg, -EFAULT);
+		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+			if (!(val & (1 << i)))
+				continue;
+			if (!mixtable[i].play) {
+				val &= ~(1 << i);
+				continue;
+			}
+			j |= mixtable[i].play;
+		}
+		spin_lock_irqsave(&s->lock, flags);
+		frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, j);
+		spin_unlock_irqrestore(&s->lock, flags);
+		return 0;
+
+		default:
+		i = _IOC_NR(cmd);
+		if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
+			return -EINVAL;
+		get_user_ret(val, (int *)arg, -EFAULT);
+		l = val & 0xff;
+		r = (val >> 8) & 0xff;
+		if (l > 100)
+			l = 100;
+		if (r > 100)
+			r = 100;
+		spin_lock_irqsave(&s->lock, flags);
+		switch (mixtable[i].type) {
+		case MT_4:
+			if (l >= 10)
+				l -= 10;
+			if (r >= 10)
+				r -= 10;
+			frobindir(s, mixtable[i].left, 0xf0, l / 6);
+			frobindir(s, mixtable[i].right, 0xf0, l / 6);
+			break;
+
+		case MT_4MUTEMONO:
+			rl = (l < 4 ? 0 : (l - 5) / 3) & 31;
+			rr = (rl >> 2) & 7;
+			wrmixer(s, mixtable[i].left, rl<<3);
+			outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2);
+			break;
+			
+		case MT_5MUTE:
+			rl = l < 4 ? 0 : (l - 5) / 3;
+			rr = r < 4 ? 0 : (r - 5) / 3;
+ 			wrmixer(s, mixtable[i].left, rl<<3);
+			wrmixer(s, mixtable[i].right, rr<<3);
+			break;
+				
+		case MT_6MUTE:
+			if (l < 6)
+				rl = 0x00;
+			else
+				rl = l * 2 / 3;
+			if (r < 6)
+				rr = 0x00;
+			else
+				rr = r * 2 / 3;
+			wrmixer(s, mixtable[i].left, rl);
+			wrmixer(s, mixtable[i].right, rr);
+			break;
+		}
+		spin_unlock_irqrestore(&s->lock, flags);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                return return_mixval(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+		if (!volidx[i])
+			return -EINVAL;
+		s->mix.vol[volidx[i]-1] = val;
+		return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+	}
+}
+
+/* --------------------------------------------------------------------- */
+
+static loff_t cm_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int cm_open_mixdev(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct cm_state *s = devs;
+
+	while (s && s->dev_mixer != minor)
+		s = s->next;
+	if (!s)
+		return -ENODEV;
+       	VALIDATE_STATE(s);
+	file->private_data = s;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int cm_release_mixdev(struct inode *inode, struct file *file)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	
+	VALIDATE_STATE(s);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int cm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	return mixer_ioctl((struct cm_state *)file->private_data, cmd, arg);
+}
+
+static /*const*/ struct file_operations cm_mixer_fops = {
+	&cm_llseek,
+	NULL,  /* read */
+	NULL,  /* write */
+	NULL,  /* readdir */
+	NULL,  /* poll */
+	&cm_ioctl_mixdev,
+	NULL,  /* mmap */
+	&cm_open_mixdev,
+	NULL,	/* flush */
+	&cm_release_mixdev,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+
+/* --------------------------------------------------------------------- */
+
+static int drain_dac(struct cm_state *s, int nonblock)
+{
+        DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int count, tmo;
+
+	if (s->dma_dac.mapped || !s->dma_dac.ready)
+		return 0;
+        current->state = TASK_INTERRUPTIBLE;
+        add_wait_queue(&s->dma_dac.wait, &wait);
+        for (;;) {
+                spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_dac.count;
+                spin_unlock_irqrestore(&s->lock, flags);
+		if (count <= 0)
+			break;
+		if (signal_pending(current))
+                        break;
+                if (nonblock) {
+                        remove_wait_queue(&s->dma_dac.wait, &wait);
+                        current->state = TASK_RUNNING;
+                        return -EBUSY;
+                }
+		tmo = (count * HZ) / s->ratedac;
+		tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK];
+		if (!schedule_timeout(tmo ? : 1) && tmo)
+			printk(KERN_DEBUG "cm: dma timed out??\n");
+        }
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+        current->state = TASK_RUNNING;
+        if (signal_pending(current))
+                return -ERESTARTSYS;
+        return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static ssize_t cm_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned swptr;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->dma_adc.mapped)
+		return -ENXIO;
+	if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
+		return ret;
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+	ret = 0;
+#if 0
+   spin_lock_irqsave(&s->lock, flags);
+   cm_update_ptr(s);
+   spin_unlock_irqrestore(&s->lock, flags);
+#endif
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		swptr = s->dma_adc.swptr;
+		cnt = s->dma_adc.dmasize-swptr;
+		if (s->dma_adc.count < cnt)
+			cnt = s->dma_adc.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			start_adc(s);
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+			interruptible_sleep_on(&s->dma_adc.wait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
+			return ret ? ret : -EFAULT;
+		swptr = (swptr + cnt) % s->dma_adc.dmasize;
+		spin_lock_irqsave(&s->lock, flags);
+		s->dma_adc.swptr = swptr;
+		s->dma_adc.count -= cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		start_adc(s);
+	}
+	return ret;
+}
+
+static ssize_t cm_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned swptr;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->dma_dac.mapped)
+		return -ENXIO;
+	if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+		return ret;
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	ret = 0;
+#if 0
+   spin_lock_irqsave(&s->lock, flags);
+   cm_update_ptr(s);
+   spin_unlock_irqrestore(&s->lock, flags);
+#endif
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		if (s->dma_dac.count < 0) {
+			s->dma_dac.count = 0;
+			s->dma_dac.swptr = s->dma_dac.hwptr;
+		}
+		swptr = s->dma_dac.swptr;
+		cnt = s->dma_dac.dmasize-swptr;
+		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
+			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			start_dac(s);
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+			interruptible_sleep_on(&s->dma_dac.wait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
+			return ret ? ret : -EFAULT;
+		swptr = (swptr + cnt) % s->dma_dac.dmasize;
+		spin_lock_irqsave(&s->lock, flags);
+		s->dma_dac.swptr = swptr;
+		s->dma_dac.count += cnt;
+		s->dma_dac.endcleared = 0;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		start_dac(s);
+	}
+	return ret;
+}
+
+static unsigned int cm_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	VALIDATE_STATE(s);
+	if (file->f_mode & FMODE_WRITE)
+		poll_wait(file, &s->dma_dac.wait, wait);
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &s->dma_adc.wait, wait);
+	spin_lock_irqsave(&s->lock, flags);
+	cm_update_ptr(s);
+	if (file->f_mode & FMODE_READ) {
+		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+			mask |= POLLIN | POLLRDNORM;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		if (s->dma_dac.mapped) {
+			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 
+				mask |= POLLOUT | POLLWRNORM;
+		} else {
+			if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)
+				mask |= POLLOUT | POLLWRNORM;
+		}
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	return mask;
+}
+
+static int cm_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	struct dmabuf *db;
+	int ret;
+	unsigned long size;
+
+	VALIDATE_STATE(s);
+	if (vma->vm_flags & VM_WRITE) {
+		if ((ret = prog_dmabuf(s, 1)) != 0)
+			return ret;
+		db = &s->dma_dac;
+	} else if (vma->vm_flags & VM_READ) {
+		if ((ret = prog_dmabuf(s, 0)) != 0)
+			return ret;
+		db = &s->dma_adc;
+	} else 
+		return -EINVAL;
+	if (vma->vm_offset != 0)
+		return -EINVAL;
+	size = vma->vm_end - vma->vm_start;
+	if (size > (PAGE_SIZE << db->buforder))
+		return -EINVAL;
+	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+		return -EAGAIN;
+	db->mapped = 1;
+	return 0;
+}
+
+static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	unsigned long flags;
+        audio_buf_info abinfo;
+        count_info cinfo;
+	int val, mapped, ret;
+	unsigned char fmtm, fmtd;
+
+	VALIDATE_STATE(s);
+        mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
+		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_SYNC:
+		if (file->f_mode & FMODE_WRITE)
+			return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);
+		return 0;
+		
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_GETCAPS:
+		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
+		
+        case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			synchronize_irq();
+			s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;
+		}
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			synchronize_irq();
+			s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
+		}
+		return 0;
+
+        case SNDCTL_DSP_SPEED:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (val >= 0) {
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				set_adc_rate(s, val);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				set_dac_rate(s, val);
+			}
+		}
+		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+		
+        case SNDCTL_DSP_STEREO:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		fmtd = 0;
+		fmtm = ~0;
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			s->dma_adc.ready = 0;
+			if (val)
+				fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT;
+			else
+				fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			s->dma_dac.ready = 0;
+			if (val)
+				fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT;
+			else
+				fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT);
+		}
+		set_fmt(s, fmtm, fmtd);
+		return 0;
+
+        case SNDCTL_DSP_CHANNELS:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (val != 0) {
+			fmtd = 0;
+			fmtm = ~0;
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				if (val >= 2)
+					fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT;
+				else
+					fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				if (val >= 2)
+					fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT;
+				else
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 34'
echo 'File patch-2.3.4 is continued in part 35'
echo 35 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 35 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 35; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+					fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT);
+			}
+			set_fmt(s, fmtm, fmtd);
+		}
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) 
+					   : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg);
+		
+	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+                return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
+		
+	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+		get_user_ret(val, (int *)arg, -EFAULT);
+ if (val != AFMT_QUERY) {
+			fmtd = 0;
+			fmtm = ~0;
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				if (val == AFMT_S16_LE)
+					fmtd |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT;
+				else
+					fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_ADCSHIFT);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				if (val == AFMT_S16_LE)
+					fmtd |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT;
+				else
+					fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_DACSHIFT);
+			}
+			set_fmt(s, fmtm, fmtd);
+		}
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) 
+					   : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? AFMT_S16_LE : AFMT_U8, (int *)arg);
+		
+	case SNDCTL_DSP_POST:
+                return 0;
+
+        case SNDCTL_DSP_GETTRIGGER:
+		val = 0;
+		if (file->f_mode & FMODE_READ && s->enable & CM_CENABLE_RE) 
+			val |= PCM_ENABLE_INPUT;
+		if (file->f_mode & FMODE_WRITE && s->enable & CM_CENABLE_PE) 
+			val |= PCM_ENABLE_OUTPUT;
+		return put_user(val, (int *)arg);
+		
+ case SNDCTL_DSP_SETTRIGGER:
+		get_user_ret(val, (int *)arg, -EFAULT);
+		if (file->f_mode & FMODE_READ) {
+ if (val & PCM_ENABLE_INPUT) {
+				if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+					return ret;
+				start_adc(s);
+			} else
+				stop_adc(s);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+ if (val & PCM_ENABLE_OUTPUT) {
+				if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+					return ret;
+				start_dac(s);
+			} else
+				stop_dac(s);
+		}
+		return 0;
+
+	case SNDCTL_DSP_GETOSPACE:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		if (!(s->enable & CM_CENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
+			return val;
+		spin_lock_irqsave(&s->lock, flags);
+		cm_update_ptr(s);
+		abinfo.fragsize = s->dma_dac.fragsize;
+                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+                abinfo.fragstotal = s->dma_dac.numfrag;
+                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_GETISPACE:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		if (!(s->enable & CM_CENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
+			return val;
+		spin_lock_irqsave(&s->lock, flags);
+		cm_update_ptr(s);
+		abinfo.fragsize = s->dma_adc.fragsize;
+                abinfo.bytes = s->dma_adc.count;
+                abinfo.fragstotal = s->dma_adc.numfrag;
+                abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		
+        case SNDCTL_DSP_NONBLOCK:
+                file->f_flags |= O_NONBLOCK;
+                return 0;
+
+        case SNDCTL_DSP_GETODELAY:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		cm_update_ptr(s);
+                val = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		return put_user(val, (int *)arg);
+
+        case SNDCTL_DSP_GETIPTR:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		cm_update_ptr(s);
+                cinfo.bytes = s->dma_adc.total_bytes;
+                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+                cinfo.ptr = s->dma_adc.hwptr;
+		if (s->dma_adc.mapped)
+			s->dma_adc.count &= s->dma_adc.fragsize-1;
+		spin_unlock_irqrestore(&s->lock, flags);
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+        case SNDCTL_DSP_GETOPTR:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		cm_update_ptr(s);
+                cinfo.bytes = s->dma_dac.total_bytes;
+                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+                cinfo.ptr = s->dma_dac.hwptr;
+		if (s->dma_dac.mapped)
+			s->dma_dac.count &= s->dma_dac.fragsize-1;
+		spin_unlock_irqrestore(&s->lock, flags);
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+        case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE) {
+			if ((val = prog_dmabuf(s, 0)))
+				return val;
+			return put_user(s->dma_dac.fragsize, (int *)arg);
+		}
+		if ((val = prog_dmabuf(s, 1)))
+			return val;
+		return put_user(s->dma_adc.fragsize, (int *)arg);
+
+        case SNDCTL_DSP_SETFRAGMENT:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (file->f_mode & FMODE_READ) {
+			s->dma_adc.ossfragshift = val & 0xffff;
+			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
+			if (s->dma_adc.ossfragshift < 4)
+				s->dma_adc.ossfragshift = 4;
+			if (s->dma_adc.ossfragshift > 15)
+				s->dma_adc.ossfragshift = 15;
+			if (s->dma_adc.ossmaxfrags < 4)
+				s->dma_adc.ossmaxfrags = 4;
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			s->dma_dac.ossfragshift = val & 0xffff;
+			s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
+			if (s->dma_dac.ossfragshift < 4)
+				s->dma_dac.ossfragshift = 4;
+			if (s->dma_dac.ossfragshift > 15)
+				s->dma_dac.ossfragshift = 15;
+			if (s->dma_dac.ossmaxfrags < 4)
+				s->dma_dac.ossmaxfrags = 4;
+		}
+		return 0;
+
+        case SNDCTL_DSP_SUBDIVIDE:
+		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
+		    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
+			return -EINVAL;
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (val != 1 && val != 2 && val != 4)
+			return -EINVAL;
+		if (file->f_mode & FMODE_READ)
+ s->dma_adc.subdivision = val;
+		if (file->f_mode & FMODE_WRITE)
+			s->dma_dac.subdivision = val;
+		return 0;
+
+        case SOUND_PCM_READ_RATE:
+		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+
+        case SOUND_PCM_READ_CHANNELS:
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg);
+
+        case SOUND_PCM_READ_BITS:
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? 16 : 8, (int *)arg);
+
+        case SOUND_PCM_WRITE_FILTER:
+        case SNDCTL_DSP_SETSYNCRO:
+        case SOUND_PCM_READ_FILTER:
+                return -EINVAL;
+		
+	}
+	return mixer_ioctl(s, cmd, arg);
+}
+
+static int cm_open(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct cm_state *s = devs;
+	unsigned char fmtm = ~0, fmts = 0;
+
+	while (s && ((s->dev_audio ^ minor) & ~0xf))
+		s = s->next;
+	if (!s)
+		return -ENODEV;
+       	VALIDATE_STATE(s);
+	file->private_data = s;
+	/* wait for device to become free */
+	down(&s->open_sem);
+	while (s->open_mode & file->f_mode) {
+		if (file->f_flags & O_NONBLOCK) {
+			up(&s->open_sem);
+			return -EBUSY;
+		}
+		up(&s->open_sem);
+		interruptible_sleep_on(&s->open_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+ down(&s->open_sem);
+	}
+	if (file->f_mode & FMODE_READ) {
+		fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT);
+		if ((minor & 0xf) == SND_DEV_DSP16)
+			fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT;
+		s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
+		set_adc_rate(s, 8000);
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT);
+		if ((minor & 0xf) == SND_DEV_DSP16)
+			fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT;
+		s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
+		set_dac_rate(s, 8000);
+	}
+	set_fmt(s, fmtm, fmts);
+	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+	up(&s->open_sem);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int cm_release(struct inode *inode, struct file *file)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+
+	VALIDATE_STATE(s);
+	if (file->f_mode & FMODE_WRITE)
+		drain_dac(s, file->f_flags & O_NONBLOCK);
+	down(&s->open_sem);
+	if (file->f_mode & FMODE_WRITE) {
+		stop_dac(s);
+ dealloc_dmabuf(&s->dma_dac);
+	}
+	if (file->f_mode & FMODE_READ) {
+		stop_adc(s);
+		dealloc_dmabuf(&s->dma_adc);
+	}
+	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+	up(&s->open_sem);
+	wake_up(&s->open_wait);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static /*const*/ struct file_operations cm_audio_fops = {
+	&cm_llseek,
+	&cm_read,
+	&cm_write,
+	NULL,  /* readdir */
+	&cm_poll,
+	&cm_ioctl,
+	&cm_mmap,
+	&cm_open,
+	NULL,	/* flush */
+ &cm_release,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+/* --------------------------------------------------------------------- */
+
+static ssize_t cm_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+ unsigned ptr;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+	ret = 0;
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		ptr = s->midi.ird;
+		cnt = MIDIINBUF - ptr;
+		if (s->midi.icnt < cnt)
+			cnt = s->midi.icnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+ interruptible_sleep_on(&s->midi.iwait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+ if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
+			return ret ? ret : -EFAULT;
+		ptr = (ptr + cnt) % MIDIINBUF;
+		spin_lock_irqsave(&s->lock, flags);
+		s->midi.ird = ptr;
+		s->midi.icnt -= cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+	}
+	return ret;
+}
+
+static ssize_t cm_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+ unsigned ptr;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	ret = 0;
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		ptr = s->midi.owr;
+		cnt = MIDIOUTBUF - ptr;
+		if (s->midi.ocnt + cnt > MIDIOUTBUF)
+			cnt = MIDIOUTBUF - s->midi.ocnt;
+		if (cnt <= 0)
+			cm_handle_midi(s);
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+ interruptible_sleep_on(&s->midi.owait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+ if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
+			return ret ? ret : -EFAULT;
+		ptr = (ptr + cnt) % MIDIOUTBUF;
+		spin_lock_irqsave(&s->lock, flags);
+		s->midi.owr = ptr;
+		s->midi.ocnt += cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		spin_lock_irqsave(&s->lock, flags);
+		cm_handle_midi(s);
+		spin_unlock_irqrestore(&s->lock, flags);
+	}
+	return ret;
+}
+
+static unsigned int cm_midi_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	VALIDATE_STATE(s);
+	if (file->f_mode & FMODE_WRITE)
+ poll_wait(file, &s->midi.owait, wait);
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &s->midi.iwait, wait);
+	spin_lock_irqsave(&s->lock, flags);
+	if (file->f_mode & FMODE_READ) {
+ if (s->midi.icnt > 0)
+			mask |= POLLIN | POLLRDNORM;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+ if (s->midi.ocnt < MIDIOUTBUF)
+			mask |= POLLOUT | POLLWRNORM;
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	return mask;
+}
+
+static int cm_midi_open(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct cm_state *s = devs;
+	unsigned long flags;
+
+ while (s && s->dev_midi != minor)
+		s = s->next;
+	if (!s)
+		return -ENODEV;
+       	VALIDATE_STATE(s);
+	file->private_data = s;
+	/* wait for device to become free */
+	down(&s->open_sem);
+	while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
+		if (file->f_flags & O_NONBLOCK) {
+			up(&s->open_sem);
+			return -EBUSY;
+		}
+		up(&s->open_sem);
+		interruptible_sleep_on(&s->open_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+ down(&s->open_sem);
+	}
+	spin_lock_irqsave(&s->lock, flags);
+	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+		/* enable MPU-401 */
+		outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) | 4, s->iobase + CODEC_CMI_FUNCTRL1);
+		outb(0xff, s->iomidi+1); /* reset command */
+		if (!(inb(s->iomidi+1) & 0x80))
+			inb(s->iomidi);
+		outb(0x3f, s->iomidi+1); /* uart command */
+		if (!(inb(s->iomidi+1) & 0x80))
+			inb(s->iomidi);
+		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+		init_timer(&s->midi.timer);
+		s->midi.timer.expires = jiffies+1;
+		s->midi.timer.data = (unsigned long)s;
+		s->midi.timer.function = cm_midi_timer;
+		add_timer(&s->midi.timer);
+	}
+	if (file->f_mode & FMODE_READ) {
+		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
+	up(&s->open_sem);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int cm_midi_release(struct inode *inode, struct file *file)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+        DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	unsigned count, tmo;
+
+	VALIDATE_STATE(s);
+
+	if (file->f_mode & FMODE_WRITE) {
+		current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&s->midi.owait, &wait);
+		for (;;) {
+			spin_lock_irqsave(&s->lock, flags);
+ count = s->midi.ocnt;
+			spin_unlock_irqrestore(&s->lock, flags);
+			if (count <= 0)
+				break;
+			if (signal_pending(current))
+				break;
+			if (file->f_flags & O_NONBLOCK) {
+ remove_wait_queue(&s->midi.owait, &wait);
+				current->state = TASK_RUNNING;
+				return -EBUSY;
+			}
+ tmo = (count * HZ) / 3100;
+			if (!schedule_timeout(tmo ? : 1) && tmo)
+				printk(KERN_DEBUG "cm: midi timed out??\n");
+		}
+		remove_wait_queue(&s->midi.owait, &wait);
+		current->state = TASK_RUNNING;
+	}
+	down(&s->open_sem);
+	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
+	spin_lock_irqsave(&s->lock, flags);
+	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+		del_timer(&s->midi.timer);		
+		outb(0xff, s->iomidi+1); /* reset command */
+		if (!(inb(s->iomidi+1) & 0x80))
+			inb(s->iomidi);
+		/* disable MPU-401 */
+		outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) & ~4, s->iobase + CODEC_CMI_FUNCTRL1);
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	up(&s->open_sem);
+	wake_up(&s->open_wait);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static /*const*/ struct file_operations cm_midi_fops = {
+	&cm_llseek,
+	&cm_midi_read,
+	&cm_midi_write,
+	NULL,  /* readdir */
+	&cm_midi_poll,
+	NULL,  /* ioctl */
+	NULL,  /* mmap */
+ &cm_midi_open,
+	NULL,	/* flush */
+ &cm_midi_release,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#ifdef CONFIG_SOUND_CMPCI_FM
+static int cm_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	static const unsigned char op_offset[18] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+		0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+		0x10, 0x11, 0x12, 0x13, 0x14, 0x15
+	};
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	struct dm_fm_voice v;
+	struct dm_fm_note n;
+	struct dm_fm_params p;
+	unsigned int io;
+	unsigned int regb;
+
+	switch (cmd) {		
+	case FM_IOCTL_RESET:
+		for (regb = 0xb0; regb < 0xb9; regb++) {
+			outb(regb, s->iosynth);
+			outb(0, s->iosynth+1);
+			outb(regb, s->iosynth+2);
+			outb(0, s->iosynth+3);
+		}
+		return 0;
+
+	case FM_IOCTL_PLAY_NOTE:
+		if (copy_from_user(&n, (void *)arg, sizeof(n)))
+			return -EFAULT;
+		if (n.voice >= 18)
+			return -EINVAL;
+		if (n.voice >= 9) {
+			regb = n.voice - 9;
+			io = s->iosynth+2;
+		} else {
+			regb = n.voice;
+			io = s->iosynth;
+		}
+		outb(0xa0 + regb, io);
+		outb(n.fnum & 0xff, io+1);
+		outb(0xb0 + regb, io);
+		outb(((n.fnum >> 8) & 3) | ((n.octave & 7) << 2) | ((n.key_on & 1) << 5), io+1);
+		return 0;
+
+	case FM_IOCTL_SET_VOICE:
+		if (copy_from_user(&v, (void *)arg, sizeof(v)))
+			return -EFAULT;
+		if (v.voice >= 18)
+			return -EINVAL;
+		regb = op_offset[v.voice];
+		io = s->iosynth + ((v.op & 1) << 1);
+		outb(0x20 + regb, io);
+		outb(((v.am & 1) << 7) | ((v.vibrato & 1) << 6) | ((v.do_sustain & 1) << 5) | 
+		     ((v.kbd_scale & 1) << 4) | (v.harmonic & 0xf), io+1);
+		outb(0x40 + regb, io);
+		outb(((v.scale_level & 0x3) << 6) | (v.volume & 0x3f), io+1);
+		outb(0x60 + regb, io);
+		outb(((v.attack & 0xf) << 4) | (v.decay & 0xf), io+1);
+		outb(0x80 + regb, io);
+		outb(((v.sustain & 0xf) << 4) | (v.release & 0xf), io+1);
+		outb(0xe0 + regb, io);
+		outb(v.waveform & 0x7, io+1);
+		if (n.voice >= 9) {
+			regb = n.voice - 9;
+			io = s->iosynth+2;
+		} else {
+			regb = n.voice;
+			io = s->iosynth;
+		}
+		outb(0xc0 + regb, io);
+		outb(((v.right & 1) << 5) | ((v.left & 1) << 4) | ((v.feedback & 7) << 1) |
+		     (v.connection & 1), io+1);
+		return 0;
+		
+	case FM_IOCTL_SET_PARAMS:
+		if (copy_from_user(&p, (void *)arg, sizeof(p)))
+			return -EFAULT;
+		outb(0x08, s->iosynth);
+		outb((p.kbd_split & 1) << 6, s->iosynth+1);
+		outb(0xbd, s->iosynth);
+		outb(((p.am_depth & 1) << 7) | ((p.vib_depth & 1) << 6) | ((p.rhythm & 1) << 5) | ((p.bass & 1) << 4) |
+		     ((p.snare & 1) << 3) | ((p.tomtom & 1) << 2) | ((p.cymbal & 1) << 1) | (p.hihat & 1), s->iosynth+1);
+		return 0;
+
+	case FM_IOCTL_SET_OPL:
+		outb(4, s->iosynth+2);
+		outb(arg, s->iosynth+3);
+		return 0;
+
+	case FM_IOCTL_SET_MODE:
+		outb(5, s->iosynth+2);
+		outb(arg & 1, s->iosynth+3);
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int cm_dmfm_open(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct cm_state *s = devs;
+
+ while (s && s->dev_dmfm != minor)
+		s = s->next;
+	if (!s)
+		return -ENODEV;
+       	VALIDATE_STATE(s);
+	file->private_data = s;
+	/* wait for device to become free */
+	down(&s->open_sem);
+	while (s->open_mode & FMODE_DMFM) {
+		if (file->f_flags & O_NONBLOCK) {
+			up(&s->open_sem);
+			return -EBUSY;
+		}
+		up(&s->open_sem);
+		interruptible_sleep_on(&s->open_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		down(&s->open_sem);
+	}
+	/* init the stuff */
+	outb(1, s->iosynth);
+	outb(0x20, s->iosynth+1); /* enable waveforms */
+	outb(4, s->iosynth+2);
+	outb(0, s->iosynth+3);  /* no 4op enabled */
+	outb(5, s->iosynth+2);
+	outb(1, s->iosynth+3);  /* enable OPL3 */
+	s->open_mode |= FMODE_DMFM;
+	up(&s->open_sem);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int cm_dmfm_release(struct inode *inode, struct file *file)
+{
+	struct cm_state *s = (struct cm_state *)file->private_data;
+	unsigned int regb;
+
+	VALIDATE_STATE(s);
+	down(&s->open_sem);
+	s->open_mode &= ~FMODE_DMFM;
+	for (regb = 0xb0; regb < 0xb9; regb++) {
+		outb(regb, s->iosynth);
+		outb(0, s->iosynth+1);
+		outb(regb, s->iosynth+2);
+		outb(0, s->iosynth+3);
+	}
+	up(&s->open_sem);
+	wake_up(&s->open_wait);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static /*const*/ struct file_operations cm_dmfm_fops = {
+	&cm_llseek,
+	NULL,  /* read */
+	NULL,  /* write */
+	NULL,  /* readdir */
+	NULL,  /* poll */
+ &cm_dmfm_ioctl,
+	NULL,  /* mmap */
+ &cm_dmfm_open,
+	NULL,	/* flush */
+ &cm_dmfm_release,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+#endif /* CONFIG_SOUND_CMPCI_FM */
+
+/* --------------------------------------------------------------------- */
+
+/* maximum number of devices */
+#define NR_DEVICE 5
+
+#if 0
+static int reverb[NR_DEVICE] = { 0, };
+
+static int wavetable[NR_DEVICE] = { 0, };
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static struct initvol {
+	int mixch;
+	int vol;
+} initvol[] __initdata = {
+	{ SOUND_MIXER_WRITE_CD, 0x4040 },
+	{ SOUND_MIXER_WRITE_LINE, 0x4040 },
+	{ SOUND_MIXER_WRITE_MIC, 0x4040 },
+	{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },
+	{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },
+	{ SOUND_MIXER_WRITE_PCM, 0x4040 }
+};
+
+#ifdef MODULE
+__initfunc(int init_module(void))
+#else
+__initfunc(int init_cmpci(void))
+#endif
+{
+	struct cm_state *s;
+	struct pci_dev *pcidev = NULL;
+	mm_segment_t fs;
+	int i, val, index = 0;
+	struct {
+		unsigned short	deviceid;
+		char		*devicename;
+	} devicetable[] =
+	{
+		{ PCI_DEVICE_ID_CMEDIA_CM8338A, "CM8338A" },
+		{ PCI_DEVICE_ID_CMEDIA_CM8338B, "CM8338B" },
+		{ PCI_DEVICE_ID_CMEDIA_CM8738,  "CM8738" },
+	};
+	char	*devicename = "unknown";
+
+#ifdef CONFIG_PCI
+	if (!pci_present())   /* No PCI bus in this machine! */
+#endif
+		return -ENODEV;
+	printk(KERN_INFO "cm: version v1.1 time " __TIME__ " " __DATE__ "\n");
+#if 0
+	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
+		printk(KERN_INFO "cm: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
+#endif
+	while (index < NR_DEVICE && pcidev == NULL && (
+ 	       (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, pcidev)) ||
+	       (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, pcidev)) ||
+	       (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, pcidev)))) {
+		if (pcidev->irq == 0)
+			continue;
+		if (!(s = kmalloc(sizeof(struct cm_state), GFP_KERNEL))) {
+			printk(KERN_WARNING "cm: out of memory\n");
+			continue;
+		}
+		/* search device name */
+		for (i = 0; i < sizeof(devicetable) / sizeof(devicetable[0]); i++)
+		{
+			if (devicetable[i].deviceid == pcidev->device)
+			{
+				devicename = devicetable[i].devicename;
+				break;
+			}
+		}
+		memset(s, 0, sizeof(struct cm_state));
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_waitqueue_head(&s->midi.iwait);
+		init_waitqueue_head(&s->midi.owait);
+		init_MUTEX(&s->open_sem);
+		s->magic = CM_MAGIC;
+		s->iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+#ifdef CONFIG_SOUND_CMPCI_FM
+		s->iosynth = 0x388;
+#endif
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+		s->iomidi = 0x330;
+#endif
+		if (s->iobase == 0)
+			continue;
+		s->irq = pcidev->irq;
+
+		if (check_region(s->iobase, CM_EXTENT_CODEC)) {
+			printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1);
+			goto err_region5;
+		}
+		request_region(s->iobase, CM_EXTENT_CODEC, "cmpci");
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+		if (check_region(s->iomidi, CM_EXTENT_MIDI)) {
+			printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1);
+			goto err_region4;
+		}
+		request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi");
+		/* set IO based at 0x330 */
+		outb(inb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3) & ~0x60, s->iobase + CODEC_CMI_LEGACY_CTRL + 3);
+#endif
+#ifdef CONFIG_SOUND_CMPCI_FM
+		if (check_region(s->iosynth, CM_EXTENT_SYNTH)) {
+			printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1);
+			goto err_region1;
+		}
+		request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM");
+		/* enable FM */
+		outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 2) | 8, s->iobase + CODEC_CMI_MISC_CTRL);
+#endif
+		/* initialize codec registers */
+		outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2);  /* disable ints */
+		outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* reset channels */
+		/* reset mixer */
+		wrmixer(s, DSP_MIX_DATARESETIDX, 0);
+
+		/* request irq */
+		if (request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s)) {
+			printk(KERN_ERR "cm: irq %u in use\n", s->irq);
+			goto err_irq;
+		}
+		printk(KERN_INFO "cm: found %s adapter at io %#06x irq %u\n",
+		       devicename, s->iobase, s->irq);
+		/* register devices */
+		if ((s->dev_audio = register_sound_dsp(&cm_audio_fops, -1)) < 0)
+			goto err_dev1;
+		if ((s->dev_mixer = register_sound_mixer(&cm_mixer_fops, -1)) < 0)
+			goto err_dev2;
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+		if ((s->dev_midi = register_sound_midi(&cm_midi_fops, -1)) < 0)
+			goto err_dev3;
+#endif
+#ifdef CONFIG_SOUND_CMPCI_FM
+		if ((s->dev_dmfm = register_sound_special(&cm_dmfm_fops, 15 /* ?? */)) < 0)
+			goto err_dev4;
+#endif
+		/* initialize the chips */
+		fs = get_fs();
+		set_fs(KERNEL_DS);
+		/* set mixer output */
+		frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, 0x1f);
+		/* set mixer input */
+		val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD|SOUND_MASK_MIC;
+		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+			val = initvol[i].vol;
+			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+		}
+		set_fs(fs);
+		/* queue it for later freeing */
+		s->next = devs;
+		devs = s;
+		index++;
+		continue;
+
+	err_dev4:
+		unregister_sound_midi(s->dev_midi);
+	err_dev3:
+		unregister_sound_mixer(s->dev_mixer);
+	err_dev2:
+		unregister_sound_dsp(s->dev_audio);
+	err_dev1:
+		printk(KERN_ERR "cm: cannot register misc device\n");
+		free_irq(s->irq, s);
+	err_irq:
+#ifdef CONFIG_SOUND_CMPCI_FM
+		release_region(s->iosynth, CM_EXTENT_SYNTH);
+	err_region1:
+#endif
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+		release_region(s->iomidi, CM_EXTENT_MIDI);
+#endif
+	err_region4:
+		release_region(s->iobase, CM_EXTENT_CODEC);
+	err_region5:
+		kfree_s(s, sizeof(struct cm_state));
+	}
+	if (!devs) {
+		if (wavetable_mem)
+			free_pages(wavetable_mem, 20-PAGE_SHIFT);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+
+#if 0
+MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
+#endif
+
+MODULE_AUTHOR("ChenLi Tien, clt...@home.com");
+MODULE_DESCRIPTION("CMPCI Audio Driver");
+
+void cleanup_module(void)
+{
+	struct cm_state *s;
+
+	while ((s = devs)) {
+		devs = devs->next;
+		outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2);  /* disable ints */
+		synchronize_irq();
+		outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* reset channels */
+		free_irq(s->irq, s);
+
+		/* reset mixer */
+		wrmixer(s, DSP_MIX_DATARESETIDX, 0);
+
+		release_region(s->iobase, CM_EXTENT_CODEC);
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+		release_region(s->iomidi, CM_EXTENT_MIDI);
+#endif
+#ifdef CONFIG_SOUND_CMPCI_FM
+		release_region(s->iosynth, CM_EXTENT_SYNTH);
+#endif
+		unregister_sound_dsp(s->dev_audio);
+		unregister_sound_mixer(s->dev_mixer);
+#ifdef CONFIG_SOUND_CMPCI_MIDI
+		unregister_sound_midi(s->dev_midi);
+#endif
+#ifdef CONFIG_SOUND_CMPCI_FM
+		unregister_sound_special(s->dev_dmfm);
+#endif
+		kfree_s(s, sizeof(struct cm_state));
+	}
+	if (wavetable_mem)
+		free_pages(wavetable_mem, 20-PAGE_SHIFT);
+	printk(KERN_INFO "cm: unloading\n");
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.3/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.3/linux/drivers/sound/es1370.c	Fri May 14 18:55:22 1999
+++ linux/drivers/sound/es1370.c	Sat May 22 13:05:35 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.3.3/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.3.3/linux/drivers/sound/lowlevel/awe_wave.c	Mon May 17 09:55:22 1999
+++ linux/drivers/sound/lowlevel/awe_wave.c	Wed May 26 09:35:00 1999
@@ -979,10 +979,10 @@
X }
X #else
X 
-static DECLARE_WAIT_QUEUE_HEAD(awe_sleeper);
X static void awe_wait(unsigned short delay)
X {
-	interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((HZ*(unsigned long)delay + 44099)/44100);
X }
X #endif /* wait by loop */
X 
diff -u --recursive --new-file v2.3.3/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.3.3/linux/drivers/sound/sb_common.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/sound/sb_common.c	Wed May 26 09:35:00 1999
@@ -742,10 +742,7 @@
X 					hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";
X 				break;
X 			case MDL_ESS:
-				if (!ess_dsp_init(devc, hw_config)) {
-					release_region (hw_config->io_base, 16);
-					return 0;
-				}
+				ess_dsp_init(devc, hw_config);
X 				break;
X 			}
X 			break;
@@ -887,6 +884,9 @@
X 
X 	if (devc && devc->base == hw_config->io_base)
X 	{
+		if ((devc->model & MDL_ESS) && devc->pcibase)
+			release_region(devc->pcibase, 8);
+
X 		release_region(devc->base, 16);
X 
X 		if (!(devc->caps & SB_NO_AUDIO))
@@ -1190,7 +1190,16 @@
X 
X void attach_sbmpu(struct address_info *hw_config)
X {
-#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
+	if (last_sb->model == MDL_ESS) {
+#if defined(CONFIG_SOUND_MPU401)
+		attach_mpu401(hw_config);
+		if (last_sb->irq == -hw_config->irq) {
+			last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
+		}
+#endif
+		return;
+	}
+#if defined(CONFIG_UART401)
X 	attach_uart401(hw_config);
X 	last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc;
X #endif
@@ -1198,7 +1207,6 @@
X 
X int probe_sbmpu(struct address_info *hw_config)
X {
-#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
X 	sb_devc *devc = last_devc;
X 
X 	if (last_devc == NULL)
@@ -1209,6 +1217,23 @@
X 	if (hw_config->io_base <= 0)
X 		return 0;
X 
+#if defined(CONFIG_SOUND_MPU401)
+	if (devc->model == MDL_ESS)
+	{
+		if (check_region(hw_config->io_base, 2))
+		{
+			printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
+			return 0;
+		}
+		if (!ess_midi_init(devc, hw_config))
+			return 0;
+		hw_config->name = "ESS1xxx MPU";
+		devc->midi_irq_cookie = -1;
+		return probe_mpu401(hw_config);
+	}
+#endif
+
+#if defined(CONFIG_UART401)
X 	if (check_region(hw_config->io_base, 4))
X 	{
X 		printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
@@ -1228,14 +1253,6 @@
X 				sb16_set_mpu_port(devc, hw_config);
X 			break;
X 
-		case MDL_ESS:
-			if (hw_config->irq < 3 || hw_config->irq == devc->irq)
-				hw_config->irq = -devc->irq;
-			if (!ess_midi_init(devc, hw_config))
-				return 0;
-			hw_config->name = "ESS ES1688";
-			break;
-
X 		case MDL_JAZZ:
X 			if (hw_config->irq < 3 || hw_config->irq == devc->irq)
X 				hw_config->irq = -devc->irq;
@@ -1258,7 +1275,13 @@
X 
X void unload_sbmpu(struct address_info *hw_config)
X {
-#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
+#if defined(CONFIG_SOUND_MPU401)
+	if (!strcmp (hw_config->name, "ESS1xxx MPU")) {
+		unload_mpu401(hw_config);
+		return;
+	}
+#endif
+#if defined(CONFIG_UART401)
X 	unload_uart401(hw_config);
X #endif
X }
diff -u --recursive --new-file v2.3.3/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c
--- v2.3.3/linux/drivers/sound/sb_ess.c	Mon May 10 13:01:21 1999
+++ linux/drivers/sound/sb_ess.c	Wed May 26 09:35:00 1999
@@ -40,6 +40,10 @@
X  *								recording problems for high samplerates. I
X  *								fixed this by removing ess_calc_best_speed ()
X  *								and just doing what the documentation says. 
+ *Javier Achirica(May 15 1999): Major cleanup, MPU IRQ sharing, hardware
+ *								volume support, PNP chip configuration,
+ *								full duplex in most cards, sample rate fine
+ *								tuning.
X  *
X  * This files contains ESS chip specifics. It's based on the existing ESS
X  * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
@@ -192,12 +196,27 @@
X 
X int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */
X 
+#define SUBMDL_ES688	0x00	/* Subtype ES688 for specific handling */
+#define SUBMDL_ES1688	0x08	/* Subtype ES1688 for specific handling */
X #define SUBMDL_ES1788	0x10	/* Subtype ES1788 for specific handling */
X #define SUBMDL_ES1868	0x11	/* Subtype ES1868 for specific handling */
X #define SUBMDL_ES1869	0x12	/* Subtype ES1869 for specific handling */
X #define SUBMDL_ES1878	0x13	/* Subtype ES1878 for specific handling */
-#define SUBMDL_ES1887	0x14	/* Subtype ES1887 for specific handling */
-#define SUBMDL_ES1888	0x15	/* Subtype ES1888 for specific handling */
+#define SUBMDL_ES1879	0x14	/* Subtype ES1879 for specific handling */
+#define SUBMDL_ES1887	0x15	/* Subtype ES1887 for specific handling */
+#define SUBMDL_ES1888	0x16	/* Subtype ES1888 for specific handling */
+
+	/* Recording mixer, stereo full duplex */
+#define ESSCAP_NEW		0x00000100
+	/* ISA PnP configuration */
+#define ESSCAP_PNP		0x00000200
+	/* Full duplex, 6-bit volume, hardware volume controls */
+#define ESSCAP_ES18		0x00000400
+	/* New interrupt handling system (ESS 1887) */
+#define ESSCAP_IRQ		0x00000800
+
+#define ESSFMT_16		0x00000001
+#define ESSFMT_SIGNED	0x00000004
X 
X #ifdef FKS_LOGGING
X static void ess_show_mixerregs (sb_devc *devc);
@@ -213,52 +232,6 @@
X  *																			*
X  ****************************************************************************/
X 
-struct ess_command {short cmd; short data;};
-
-/*
- * Commands for initializing Audio 1 for input (record)
- */
-static struct ess_command ess_i08m[] =		/* input 8 bit mono */
-	{ {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
-static struct ess_command ess_i16m[] =		/* input 16 bit mono */
-	{ {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
-static struct ess_command ess_i08s[] =		/* input 8 bit stereo */
-	{ {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
-static struct ess_command ess_i16s[] =		/* input 16 bit stereo */
-	{ {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
-
-static struct ess_command *ess_inp_cmds[] =
-	{ ess_i08m, ess_i16m, ess_i08s, ess_i16s };
-
-
-/*
- * Commands for initializing Audio 1 for output (playback)
- */
-static struct ess_command ess_o08m[] =		/* output 8 bit mono */
-	{ {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
-static struct ess_command ess_o16m[] =		/* output 16 bit mono */
-	{ {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
-static struct ess_command ess_o08s[] =		/* output 8 bit stereo */
-	{ {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
-static struct ess_command ess_o16s[] =		/* output 16 bit stereo */
-	{ {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
-
-static struct ess_command *ess_out_cmds[] =
-	{ ess_o08m, ess_o16m, ess_o08s, ess_o16s };
-
-static void ess_exec_commands
-	(sb_devc *devc, struct ess_command *cmdtab[])
-{
-	struct ess_command *cmd;
-
-	cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ];
-
-	while (cmd->cmd != -1) {
-		ess_write (devc, cmd->cmd, cmd->data);
-		cmd++;
-	}
-}
-
X static void ess_change
X 	(sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val)
X {
@@ -298,56 +271,22 @@
X 	devc->irq_mode = IMODE_INPUT;
X }
X 
-static int ess_calc_div (int clock, int revert, int *speedp, int *diffp)
+static int ess_calc_div (int clock, int *speedp, int *diffp)
X {
X 	int divider;
X 	int speed, diff;
-	int retval;
X 
X 	speed   = *speedp;
X 	divider = (clock + speed / 2) / speed;
-	retval  = revert - divider;
-	if (retval > revert - 1) {
-		retval  = revert - 1;
-		divider = revert - retval;
-	}
-	/* This line is suggested. Must be wrong I think
-	*speedp = (clock + divider / 2) / divider;
-	So I chose the next one */
-
+	if (divider > 127) {
+		divider = 127;
+	}
X 	*speedp	= clock / divider;
X 	diff	= speed - *speedp;
-	if (diff < 0) diff =-diff;
-	*diffp  = diff;
-
-	return retval;
-}
-
-#ifdef OBSOLETE
-static int ess_calc_best_speed
-	(int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
-{
-	int speed1 = *speedp, speed2 = *speedp;
-	int div1, div2;
-	int diff1, diff2;
-	int retval;
-
-	div1 = ess_calc_div (clock1, rev1, &speed1, &diff1);
-	div2 = ess_calc_div (clock2, rev2, &speed2, &diff2);
-
-	if (diff1 < diff2) {
-		*divp   = div1;
-		*speedp = speed1;
-		retval  = 1;
-	} else {
-		*divp   = div2;
-		*speedp = speed2;
-		retval  = 2;
-	}
+	*diffp = diff < 0 ? -diff : diff;
X 
-	return retval;
+	return 128 - divider;
X }
-#endif
X 
X /*
X  * Depending on the audiochannel ESS devices can
@@ -359,21 +298,30 @@
X  */
X static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
X {
-	int diff = 0, div;
+	int speed1 = *speedp, speed2 = *speedp;
+	int div1, div2;
+	int diff1, diff2;
X 
-	if (devc->duplex) {
-		/*
-		 * The 0x80 is important for the first audio channel
-		 */
-		div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
+	if (devc->caps & ESSCAP_NEW) {
+		div1 = 0x000 | ess_calc_div (793800, &speed1, &diff1);
+		div2 = 0x080 | ess_calc_div (768000, &speed2, &diff2);
X 	} else {
X 		if (*speedp > 22000) {
-			div = 0x80 | ess_calc_div (795500, 256, speedp, &diff);
+			div1 = 0x080 | ess_calc_div (795444, &speed1, &diff1);
+			div2 = 0x180 | ess_calc_div (793800, &speed2, &diff2);
X 		} else {
-			div = 0x00 | ess_calc_div (397700, 128, speedp, &diff);
+			div1 = 0x000 | ess_calc_div (397722, &speed1, &diff1);
+			div2 = 0x100 | ess_calc_div (396900, &speed2, &diff2);
X 		}
X 	}
-	*divp = div;
+
+	if (diff1 < diff2) {
+		*divp   = div1;
+		*speedp = speed1;
+	} else {
+		*divp   = div2;
+		*speedp = speed2;
+	}
X }
X 
X static void ess_speed (sb_devc *devc, int audionum)
@@ -392,21 +340,13 @@
X 
X 	div2 = 256 - 7160000 / (speed * 82);
X 
-	if (!devc->duplex) audionum = 1;
-
-	if (audionum == 1) {
-		/* Change behaviour of register A1 *
-		sb_chg_mixer(devc, 0x71, 0x20, 0x20)
-		* For ES1869 only??? */
-		ess_write (devc, 0xa1, div);
-		ess_write (devc, 0xa2, div2);
-	} else {
+	if ((devc->caps & ESSCAP_NEW) && audionum != 1) {
X 		ess_setmixer (devc, 0x70, div);
-		/*
-		 * FKS: fascinating: 0x72 doesn't seem to work.
-		 */
-		ess_write (devc, 0xa2, div2);
X 		ess_setmixer (devc, 0x72, div2);
+	} else {
+		ess_change (devc, 0xba, 0x40, (div & 0x100) ? 0x40 : 0x00);
+		ess_write (devc, 0xa1, div & 0xff);
+		ess_write (devc, 0xa2, div2);
X 	}
X }
X 
@@ -414,77 +354,14 @@
X {
X 	sb_devc *devc = audio_devs[dev]->devc;
X 
-	ess_speed(devc, 1);
-
-	sb_dsp_command(devc, DSP_CMD_SPKOFF);
-
X 	ess_write (devc, 0xb8, 0x0e);	/* Auto init DMA mode */
-	ess_change (devc, 0xa8, 0x03, 3 - devc->channels);	/* Mono/stereo */
-	ess_write (devc, 0xb9, 2);	/* Demand mode (4 bytes/DMA request) */
-
-	ess_exec_commands (devc, ess_inp_cmds);
-
-	ess_change (devc, 0xb1, 0xf0, 0x50);
-	ess_change (devc, 0xb2, 0xf0, 0x50);
+	ess_change (devc, 0xa8, 0x0b, 3 - devc->channels);	/* Mono/stereo */
X 
-	devc->trigger_bits = 0;
-	return 0;
-}
-
-static int ess_audio_prepare_for_output_audio1 (int dev, int bsize, int bcount)
-{
-	sb_devc *devc = audio_devs[dev]->devc;
-
-	sb_dsp_reset(devc);
X 	ess_speed(devc, 1);
-	ess_write (devc, 0xb8, 4);	/* Auto init DMA mode */
-	ess_change (devc, 0xa8, 0x03, 3 - devc->channels);	/* Mono/stereo */
-	ess_write (devc, 0xb9, 2);	/* Demand mode (4 bytes/request) */
-
-	ess_exec_commands (devc, ess_out_cmds);
-
-	ess_change (devc, 0xb1, 0xf0, 0x50);	/* Enable DMA */
-	ess_change (devc, 0xb2, 0xf0, 0x50);	/* Enable IRQ */
X 
-	sb_dsp_command(devc, DSP_CMD_SPKON);	/* There be sound! */
-
-	devc->trigger_bits = 0;
-	return 0;
-}
-
-static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount)
-{
-	sb_devc *devc = audio_devs[dev]->devc;
-	unsigned char bits;
-
-/* FKS: qqq
-	sb_dsp_reset(devc);
-*/
-
-	/*
-	 * Auto-Initialize:
-	 * DMA mode + demand mode (8 bytes/request, yes I want it all!)
-	 * But leave 16-bit DMA bit untouched!
-	 */
-	ess_chgmixer (devc, 0x78, 0xd0, 0xd0);
-
-	ess_speed(devc, 2);
-
-	/* bits 4:3 on ES1887 represent recording source. Keep them! */
-	bits = ess_getmixer (devc, 0x7a) & 0x18;
-
-	/* Set stereo/mono */
-	if (devc->channels != 1) bits |= 0x02;
-
-	/* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */
-	if (devc->bits != AFMT_U8) bits |= 0x05;	/* 16 bit */
-
-	/* Enable DMA, IRQ will be shared (hopefully)*/
-	bits |= 0x60;
-
-	ess_setmixer (devc, 0x7a, bits);
-
-	ess_mixer_reload (devc, SOUND_MIXER_PCM);	/* There be sound! */
+    ess_write (devc, 0xb7, (devc->bits & ESSFMT_SIGNED) ? 0x71 : 0x51);
+    ess_write (devc, 0xb7, 0x90 | ((devc->bits & ESSFMT_SIGNED) ? 0x20 : 0) |
+		((devc->bits & ESSFMT_16) ? 4 : 0) | ((devc->channels > 1) ? 8 : 0x40));
X 
X 	devc->trigger_bits = 0;
X 	return 0;
@@ -500,144 +377,79 @@
X #endif
X 
X 	if (devc->duplex) {
-		return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount);
-	} else {
-		return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount);
-	}
-}
-
-static void ess_audio_halt_xfer(int dev)
-{
-	unsigned long flags;
-	sb_devc *devc = audio_devs[dev]->devc;
-
-	save_flags(flags);
-	cli();
-	sb_dsp_reset(devc);
-	restore_flags(flags);
-
-	/*
-	 * Audio 2 may still be operational! Creates awful sounds!
-	 */
-	if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00);
-}
-
-static void ess_audio_start_input
-	(int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
-	int count = nr_bytes;
-	sb_devc *devc = audio_devs[dev]->devc;
-	short c = -nr_bytes;
-
-	/*
-	 * Start a DMA input to the buffer pointed by dmaqtail
-	 */
-
-	if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1;
-	count--;
-
-	devc->irq_mode = IMODE_INPUT;
-
-	ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
-	ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-
-	ess_change (devc, 0xb8, 0x0f, 0x0f);	/* Go */
-	devc->intr_active = 1;
-}
+		ess_speed(devc, 2);
X 
-static void ess_audio_output_block_audio1
-	(int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
-	int count = nr_bytes;
-	sb_devc *devc = audio_devs[dev]->devc;
-	short c = -nr_bytes;
+	    ess_chgmixer (devc, 0x7a, 0x07, ((devc->bits & ESSFMT_SIGNED) ? 4 : 0) |
+			((devc->bits & ESSFMT_16) ? 1 : 0) | ((devc->channels > 1) ? 2 : 0));
X 
-	if (audio_devs[dev]->dmap_out->dma > 3)
-		count >>= 1;
-	count--;
+		if (devc->caps & ESSCAP_NEW)
+			ess_mixer_reload (devc, SOUND_MIXER_PCM);	/* There be sound! */
+		else
+			sb_dsp_command(devc, DSP_CMD_SPKON);	/* There be sound! */
+	} else {
+		ess_write (devc, 0xb8, 4);	/* Auto init DMA mode */
+		ess_change (devc, 0xa8, 0x03, 3 - devc->channels);	/* Mono/stereo */
X 
-	devc->irq_mode = IMODE_OUTPUT;
+		ess_speed(devc, 1);
X 
-	ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
-	ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+	    ess_write (devc, 0xb6, (devc->bits & ESSFMT_SIGNED) ? 0 : 0x80);
+	    ess_write (devc, 0xb7, (devc->bits & ESSFMT_SIGNED) ? 0x71 : 0x51);
+	    ess_write (devc, 0xb7, 0x90 | ((devc->bits & ESSFMT_SIGNED) ? 0x20 : 0) |
+			((devc->bits & ESSFMT_16) ? 4 : 0) | ((devc->channels > 1) ? 8 : 0x40));
X 
-	ess_change (devc, 0xb8, 0x05, 0x05);	/* Go */
-	devc->intr_active = 1;
+		sb_dsp_command(devc, DSP_CMD_SPKON);	/* There be sound! */
+	}
+	devc->trigger_bits = 0;
+	return 0;
X }
X 
-static void ess_audio_output_block_audio2
-	(int dev, unsigned long buf, int nr_bytes, int intrflag)
+static void ess_audio_halt_xfer(int dev)
X {
-	int count = nr_bytes;
X 	sb_devc *devc = audio_devs[dev]->devc;
-	short c = -nr_bytes;
X 
-	if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1;
-	count--;
+	sb_dsp_command (devc, DSP_CMD_SPKOFF);
X 
-	ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff));
-	ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-	ess_chgmixer (devc, 0x78, 0x03, 0x03);   /* Go */
-
-	devc->irq_mode_16 = IMODE_OUTPUT;
-		devc->intr_active_16 = 1;
-}
+	if (devc->caps & ESSCAP_NEW) {
+		ess_setmixer (devc, 0x7c, 0);
+	}
X 
-static void ess_audio_output_block
-	(int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
-	sb_devc *devc = audio_devs[dev]->devc;
+	ess_change (devc, 0xb8, 0x0f, 0x00);	/* Stop */
X 
-	if (devc->duplex) {
-		ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag);
-	} else {
-		ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag);
+	if (devc->duplex) {			/* Audio 2 may still be operational! */
+		ess_chgmixer (devc, 0x78, 0x03, 0x00);
X 	}
X }
X 
-/*
- * FKS: the if-statements for both bits and bits_16 are quite alike.
- * Combine this...
- */
X static void ess_audio_trigger(int dev, int bits)
X {
X 	sb_devc *devc = audio_devs[dev]->devc;
X 
-	int bits_16 = bits & devc->irq_mode_16;
+	int bits_16 = bits & devc->irq_mode_16 & IMODE_OUTPUT;
X 	bits &= devc->irq_mode;
X 
X 	if (!bits && !bits_16) {
-		/* FKS oh oh.... wrong?? for dma 16? */
-		sb_dsp_command(devc, 0xd0);	/* Halt DMA */
+		sb_dsp_command (devc, 0xd0);			/* Halt DMA */
+		ess_chgmixer (devc, 0x78, 0x04, 0x00);	/* Halt DMA 2 */
X 	}
X 
X 	if (bits) {
-		switch (devc->irq_mode)
-		{
-			case IMODE_INPUT:
-				ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
-					devc->trg_intrflag);
-				break;
+		short c = -devc->trg_bytes;
X 
-			case IMODE_OUTPUT:
-				ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
-					devc->trg_intrflag);
-				break;
-		}
+		ess_write (devc, 0xa4, (unsigned char)((unsigned short) c & 0xff));
+		ess_write (devc, 0xa5, (unsigned char)((unsigned short) c >> 8));
+		ess_change (devc, 0xb8, 0x0f, (devc->irq_mode==IMODE_INPUT)?0x0f:0x05);
+
+		devc->intr_active = 1;
X 	}
X 
X 	if (bits_16) {
-		switch (devc->irq_mode_16) {
-		case IMODE_INPUT:
-			ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16,
-					devc->trg_intrflag_16);
-			break;
+		short c = -devc->trg_bytes_16;
X 
-		case IMODE_OUTPUT:
-			ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16,
-					devc->trg_intrflag_16);
-			break;
-		}
+		ess_setmixer (devc, 0x74, (unsigned char)((unsigned short) c & 0xff));
+		ess_setmixer (devc, 0x76, (unsigned char)((unsigned short) c >> 8));
+		ess_chgmixer (devc, 0x78, 0x03, 0x03);   /* Go */
+
+		devc->intr_active_16 = 1;
X 	}
X 
X 	devc->trigger_bits = bits | bits_16;
@@ -649,8 +461,8 @@
X 	int minspeed, maxspeed, dummydiv;
X 
X 	if (speed > 0) {
-		minspeed = (devc->duplex ? 6215  : 5000 );
-		maxspeed = (devc->duplex ? 44100 : 48000);
+		minspeed = (devc->caps & ESSCAP_NEW) ? 6047  : 3125;
+		maxspeed = 48000;
X 		if (speed < minspeed) speed = minspeed;
X 		if (speed > maxspeed) speed = maxspeed;
X 
@@ -661,38 +473,46 @@
X 	return devc->speed;
X }
X 
-/*
- * FKS: This is a one-on-one copy of sb1_audio_set_bits
- */
X static unsigned int ess_audio_set_bits(int dev, unsigned int bits)
X {
X 	sb_devc *devc = audio_devs[dev]->devc;
X 
-	if (bits != 0) {
-		if (bits == AFMT_U8 || bits == AFMT_S16_LE) {
-			devc->bits = bits;
-		} else {
-			devc->bits = AFMT_U8;
-		}
+	switch (bits) {
+		case 0:
+			break;
+		case AFMT_S16_LE:
+			devc->bits = ESSFMT_16 | ESSFMT_SIGNED;
+			break;
+		case AFMT_U16_LE:
+			devc->bits = ESSFMT_16;
+			break;
+		case AFMT_S8:
+			devc->bits = ESSFMT_SIGNED;
+			break;
+		default:
+			devc->bits = 0;
+			break;
X 	}
X 
X 	return devc->bits;
X }
X 
-/*
- * FKS: This is a one-on-one copy of sbpro_audio_set_channels
- * (*) Modified it!!
- */
X static short ess_audio_set_channels(int dev, short channels)
X {
X 	sb_devc *devc = audio_devs[dev]->devc;
X 
-	if (channels == 1 || channels == 2) devc->channels = channels;
+	if (devc->fullduplex && !(devc->caps & ESSCAP_NEW)) {
+		devc->channels = 1;
+	} else {
+		if (channels == 1 || channels == 2) {
+			devc->channels = channels;
+		}
+	}
X 
X 	return devc->channels;
X }
X 
-static struct audio_driver ess_audio_driver =   /* ESS ES688/1688 */
+static struct audio_driver ess_audio_driver =   /* ESS ES688/1688/18xx */
X {
X 	sb_audio_open,
X 	sb_audio_close,
@@ -719,7 +539,7 @@
X 		(sb_devc *devc, int *audio_flags, int *format_mask)
X {
X 	*audio_flags = DMA_AUTOMODE;
-	*format_mask |= AFMT_S16_LE;
+	*format_mask |= AFMT_S16_LE | AFMT_U16_LE | AFMT_S8;
X 
X 	if (devc->duplex) {
X 		int tmp_dma;
@@ -742,10 +562,8 @@
X  *								ESS common									*
X  *																			*
X  ****************************************************************************/
-static void ess_handle_channel
-	(char *channel, int dev, int intr_active, unsigned char flag, int irq_mode)
+static void ess_handle_channel (int dev, int irq_mode)
X {
-	if (!intr_active || !flag) return;
X #ifdef FKS_REG_LOGGING
X printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode);
X #endif
@@ -767,48 +585,77 @@
X }
X 
X /*
- * FKS: TODO!!! Finish this!
- *
- * I think midi stuff uses uart401, without interrupts.
- * So IMODE_MIDI isn't a value for devc->irq_mode.
+ * In the ESS 1888 model, how do we found out if the MPU interrupted ???
X  */
X void ess_intr (sb_devc *devc)
X {
X 	int				status;
X 	unsigned char	src;
X 
-	if (devc->submodel == SUBMDL_ES1887) {
+	if (devc->caps & ESSCAP_PNP) {
+		outb (devc->pcibase + 7, 0);		/* Mask IRQs */
+		src = inb (devc->pcibase + 6) & 0x0f;
+	} else if (devc->caps & ESSCAP_IRQ) {
X 		src = ess_getmixer (devc, 0x7f) >> 4;
X 	} else {
-		src = 0xff;
+		src = inb (DSP_STATUS) & 0x01;
+		if (devc->duplex && (ess_getmixer (devc, 0x7a) & 0x80)) {
+			src |= 0x02;
+		}
+		if ((devc->caps & ESSCAP_ES18) && (ess_getmixer (devc, 0x64) & 0x10)) {
+			src |= 0x04;
+		}
+#if defined(CONFIG_MIDI) && defined(CONFIG_SOUND_MPU401)
+		/*
+		 * This should work if dev_conf wasn't local to mpu401.c
+		 */
+#if 0
+		if ((int)devc->midi_irq_cookie >= 0 &&
+			!(inb(dev_conf[(int)devc->midi_irq_cookie].base + 1) & 0x80)) {
+			src |= 0x08;
+		}
+#endif
+#endif
X 	}
X 
X #ifdef FKS_REG_LOGGING
X printk(KERN_INFO "FKS: sbintr src=%x\n",(int)src);
X #endif
-	ess_handle_channel
-		( "Audio 1"
-		, devc->dev, devc->intr_active   , src & 0x01, devc->irq_mode   );
-	ess_handle_channel
-		( "Audio 2"
-		, devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16);
-	/*
-	 * Acknowledge interrupts
-	 */
-	if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) {
-		ess_chgmixer (devc, 0x7a, 0x80, 0x00);
+	if (src & 0x01) {
+		status = inb(DSP_DATA_AVAIL);	/* Acknowledge interrupt */
+		if (devc->intr_active)
+			ess_handle_channel (devc->dev, devc->irq_mode   );
X 	}
X 
-	if (src & 0x01) {
-		status = inb(DSP_DATA_AVAIL);
+	if (src & 0x02) {
+		ess_chgmixer (devc, 0x7a, 0x80, 0x00);	/* Acknowledge interrupt */
+		if (devc->intr_active_16)
+			ess_handle_channel (devc->dev, devc->irq_mode_16);
X 	}
-}
X 
-static void ess_extended (sb_devc * devc)
-{
-	/* Enable extended mode */
+	if (src & 0x04) {
+		int left, right;
+
+		ess_setmixer (devc, 0x66, 0x00);	/* Hardware volume IRQ ack */
+
+		left = ess_getmixer (devc, 0x60);
+		right = ess_getmixer (devc, 0x62);
X 
-	sb_dsp_command(devc, 0xc6);
+		left = (left & 0x40) ? 0 : ((left * 100 + 31)/ 63);	/* Mute or scale */
+		right = (right & 0x40) ? 0 : ((right * 100 + 31)/ 63);
+
+		devc->levels[SOUND_MIXER_VOLUME] = left | (right << 8);
+	}
+
+#if defined(CONFIG_MIDI) && defined(CONFIG_SOUND_MPU401)
+	if ((int)devc->midi_irq_cookie >= 0 && (src & 0x08)) {
+		mpuintr (devc->irq, devc->midi_irq_cookie, NULL);
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 35'
echo 'File patch-2.3.4 is continued in part 36'
echo 36 > _shar_seq_.tmp
#!/bin/sh
# this is part 38 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 38; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X 	  inode->i_sb->u.isofs_sb.s_cruft = 'y';
X 	}
X 
@@ -1201,7 +1234,7 @@
X #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
X 	if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
X 	    (volume_seq_no != 0) && (volume_seq_no != 1)) {
-		printk("Multi volume CD somehow got mounted.\n");
+		printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n");
X 	} else
X #endif IGNORE_WRONG_MULTI_VOLUME_SPECS
X 	{
diff -u --recursive --new-file v2.3.3/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v2.3.3/linux/fs/ncpfs/ioctl.c	Sat May 15 23:46:04 1999
+++ linux/fs/ncpfs/ioctl.c	Wed May 26 09:27:16 1999
@@ -89,7 +89,7 @@
X 
X 		result = ncp_request2(server, request.function, 
X 			bouncebuffer, NCP_PACKET_SIZE);
-		if (result)
+		if (result < 0)
X 			result = -EIO;
X 		else
X 			result = server->reply_size;
diff -u --recursive --new-file v2.3.3/linux/fs/open.c linux/fs/open.c
--- v2.3.3/linux/fs/open.c	Fri Apr 16 14:21:39 1999
+++ linux/fs/open.c	Mon May 24 22:47:43 1999
@@ -171,7 +171,7 @@
X 	return error;
X }
X 
-#ifndef __alpha__
+#if !(defined(__alpha__) || defined(__ia64__))
X 
X /*
X  * sys_utime() can be implemented in user-level using sys_utimes().
diff -u --recursive --new-file v2.3.3/linux/fs/select.c linux/fs/select.c
--- v2.3.3/linux/fs/select.c	Fri May 14 18:55:26 1999
+++ linux/fs/select.c	Sun May 23 23:53:45 1999
@@ -267,8 +267,12 @@
X 	}
X 
X 	ret = -EINVAL;
-	if (n < 0 || n > KFDS_NR)
+	if (n < 0)
X 		goto out_nofds;
+
+	if (n > KFDS_NR)
+		n = KFDS_NR;
+
X 	/*
X 	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
X 	 * since we used fdset we need to allocate memory in units of
diff -u --recursive --new-file v2.3.3/linux/fs/stat.c linux/fs/stat.c
--- v2.3.3/linux/fs/stat.c	Fri Nov 13 10:07:26 1998
+++ linux/fs/stat.c	Mon May 24 22:47:43 1999
@@ -24,7 +24,7 @@
X }
X 
X 
-#if !defined(__alpha__) && !defined(__sparc__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
X 
X /*
X  * For backward compatibility?  Maybe this should be moved
@@ -114,7 +114,7 @@
X }
X 
X 
-#if !defined(__alpha__) && !defined(__sparc__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
X /*
X  * For backward compatibility?  Maybe this should be moved
X  * into arch/i386 instead?
@@ -160,7 +160,7 @@
X 	return error;
X }
X 
-#if !defined(__alpha__) && !defined(__sparc__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
X 
X /*
X  * For backward compatibility?  Maybe this should be moved
@@ -208,7 +208,7 @@
X 	return error;
X }
X 
-#if !defined(__alpha__) && !defined(__sparc__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
X 
X /*
X  * For backward compatibility?  Maybe this should be moved
diff -u --recursive --new-file v2.3.3/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.3.3/linux/include/asm-alpha/processor.h	Mon May 17 09:55:23 1999
+++ linux/include/asm-alpha/processor.h	Tue May 25 14:55:05 1999
@@ -8,6 +8,12 @@
X #define __ASM_ALPHA_PROCESSOR_H
X 
X /*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+/*
X  * We have a 42-bit user address space: 4TB user VM...
X  */
X #define TASK_SIZE (0x40000000000UL)
diff -u --recursive --new-file v2.3.3/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.3.3/linux/include/asm-alpha/semaphore.h	Mon May 17 09:55:23 1999
+++ linux/include/asm-alpha/semaphore.h	Sat May 22 13:46:08 1999
@@ -17,14 +17,57 @@
X 	atomic_t count;
X 	atomic_t waking;		/* biased by -1 */
X 	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
X };
X 
-#define MUTEX ((struct semaphore) \
- { ATOMIC_INIT(1), ATOMIC_INIT(-1), NULL })
-#define MUTEX_LOCKED ((struct semaphore) \
- { ATOMIC_INIT(0), ATOMIC_INIT(-1), NULL })
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name)		, (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count)		\
+	{ ATOMIC_INIT(count), ATOMIC_INIT(-1),		\
+	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+	  __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+	/*
+	 * Logically, 
+	 *   *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+	 * except that gcc produces better initializing by parts yet.
+	 */
+
+	atomic_set(&sem->count, val);
+	atomic_set(&sem->waking, -1);
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
X 
-#define sema_init(sem, val)	atomic_set(&((sem)->count), val)
X 
X extern void __down(struct semaphore * sem);
X extern int  __down_interruptible(struct semaphore * sem);
@@ -57,8 +100,13 @@
X 	   a function that ordinarily wouldn't.  Otherwise we could
X 	   have it done by the macro directly, which can be optimized
X 	   the linker.  */
-	register void *pv __asm__("$27") = __down_failed;
+	register void *pv __asm__("$27");
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
X 	
+	pv = __down_failed;
X 	__asm__ __volatile__ (
X 		"/* semaphore down operation */\n"
X 		"1:	ldl_l	$24,%1\n"
@@ -88,8 +136,13 @@
X 	   value is in $24.  */
X 
X 	register int ret __asm__("$24");
-	register void *pv __asm__("$27") = __down_failed_interruptible;
+	register void *pv __asm__("$27");
X 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	
+	pv = __down_failed_interruptible;
X 	__asm__ __volatile__ (
X 		"/* semaphore down interruptible operation */\n"
X 		"1:	ldl_l	$24,%2\n"
@@ -144,6 +197,10 @@
X 	   } while (tmp == 0);
X 	*/
X 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	
X 	__asm__ __volatile__(
X 		"1:	ldq_l	%1,%4\n"
X 		"	lda	%3,1\n"
@@ -179,8 +236,13 @@
X 	   it's return address in $28.  The pv is loaded as usual.
X 	   The gp is clobbered (in the module case) as usual.  */
X 
-	register void *pv __asm__("$27") = __up_wakeup;
+	register void *pv __asm__("$27");
X 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	
+	pv = __up_wakeup;
X 	__asm__ __volatile__ (
X 		"/* semaphore up operation */\n"
X 		"	mb\n"
diff -u --recursive --new-file v2.3.3/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.3.3/linux/include/asm-arm/processor.h	Sat May  8 11:06:58 1999
+++ linux/include/asm-arm/processor.h	Tue May 25 14:55:05 1999
@@ -7,6 +7,12 @@
X #ifndef __ASM_ARM_PROCESSOR_H
X #define __ASM_ARM_PROCESSOR_H
X 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
X #define FP_SIZE 35
X 
X struct fp_hard_struct {
diff -u --recursive --new-file v2.3.3/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.3.3/linux/include/asm-i386/processor.h	Tue May 11 13:03:58 1999
+++ linux/include/asm-i386/processor.h	Tue May 25 14:56:06 1999
@@ -11,6 +11,13 @@
X #include <asm/math_emu.h>
X #include <asm/segment.h>
X #include <asm/page.h>
+#include <asm/types.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
X 
X /*
X  *  CPU type and hardware bug flags. Kept separately for each CPU.
@@ -279,6 +286,7 @@
X } while (0)
X 
X /* Forward declaration, a strange C thing */
+struct task_struct;
X struct mm_struct;
X 
X /* Free all resources held by a thread. */
diff -u --recursive --new-file v2.3.3/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.3.3/linux/include/asm-i386/softirq.h	Tue May 11 13:04:00 1999
+++ linux/include/asm-i386/softirq.h	Fri May 28 09:19:24 1999
@@ -40,6 +40,13 @@
X 
X extern void synchronize_bh(void);
X 
+/*
+ * This is suboptimal. We only need to disable bh's locally
+ * on this CPU...
+ */
+#define local_bh_disable()	atomic_inc(&global_bh_lock)
+#define local_bh_enable()	atomic_dec(&global_bh_lock)
+
X static inline void start_bh_atomic(void)
X {
X 	atomic_inc(&global_bh_lock);
@@ -83,6 +90,9 @@
X 	barrier();
X 	local_bh_count[smp_processor_id()]--;
X }
+
+#define local_bh_disable()	(local_bh_count[smp_processor_id()]++)
+#define local_bh_enable()	(local_bh_count[smp_processor_id()]--)
X 
X /* These are for the irq's testing the lock */
X #define softirq_trylock(cpu)	(local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1))
diff -u --recursive --new-file v2.3.3/linux/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h
--- v2.3.3/linux/include/asm-i386/spinlock.h	Tue May 11 13:03:58 1999
+++ linux/include/asm-i386/spinlock.h	Tue May 25 14:56:58 1999
@@ -1,6 +1,35 @@
X #ifndef __ASM_SPINLOCK_H
X #define __ASM_SPINLOCK_H
X 
+/*
+ * These are the generic versions of the spinlocks
+ * and read-write locks.. We should actually do a
+ * <linux/spinlock.h> with all of this. Oh, well.
+ */
+#define spin_lock_irqsave(lock, flags)		do { local_irq_save(flags);       spin_lock(lock); } while (0)
+#define spin_lock_irq(lock)			do { local_irq_disable();         spin_lock(lock); } while (0)
+#define spin_lock_bh(lock)			do { local_bh_disable();          spin_lock(lock); } while (0)
+
+#define read_lock_irqsave(lock, flags)		do { local_irq_save(flags);       read_lock(lock); } while (0)
+#define read_lock_irq(lock)			do { local_irq_disable();         read_lock(lock); } while (0)
+#define read_lock_bh(lock)			do { local_bh_disable();          read_lock(lock); } while (0)
+
+#define write_lock_irqsave(lock, flags)		do { local_irq_save(flags);      write_lock(lock); } while (0)
+#define write_lock_irq(lock)			do { local_irq_disable();        write_lock(lock); } while (0)
+#define write_lock_bh(lock)			do { local_bh_disable();         write_lock(lock); } while (0)
+
+#define spin_unlock_irqrestore(lock, flags)	do { spin_unlock(lock);  local_irq_restore(flags); } while (0)
+#define spin_unlock_irq(lock)			do { spin_unlock(lock);  local_irq_enable();       } while (0)
+#define spin_unlock_bh(lock)			do { spin_unlock(lock);  local_bh_enable();        } while (0)
+
+#define read_unlock_irqrestore(lock, flags)	do { read_unlock(lock);  local_irq_restore(flags); } while (0)
+#define read_unlock_irq(lock)			do { read_unlock(lock);  local_irq_enable();       } while (0)
+#define read_unlock_bh(lock)			do { read_unlock(lock);  local_bh_enable();        } while (0)
+
+#define write_unlock_irqrestore(lock, flags)	do { write_unlock(lock); local_irq_restore(flags); } while (0)
+#define write_unlock_irq(lock)			do { write_unlock(lock); local_irq_enable();       } while (0)
+#define write_unlock_bh(lock)			do { write_unlock(lock); local_bh_enable();        } while (0)
+
X #ifndef __SMP__
X 
X #define DEBUG_SPINLOCKS	0	/* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
@@ -25,13 +54,6 @@
X #define spin_trylock(lock)	(1)
X #define spin_unlock_wait(lock)	do { } while(0)
X #define spin_unlock(lock)	do { } while(0)
-#define spin_lock_irq(lock)	cli()
-#define spin_unlock_irq(lock)	sti()
-
-#define spin_lock_irqsave(lock, flags) \
-	do { save_flags(flags); cli(); } while (0)
-#define spin_unlock_irqrestore(lock, flags) \
-	restore_flags(flags)
X 
X #elif (DEBUG_SPINLOCKS < 2)
X 
@@ -46,13 +68,6 @@
X #define spin_lock(x)		do { (x)->lock = 1; } while (0)
X #define spin_unlock_wait(x)	do { } while (0)
X #define spin_unlock(x)		do { (x)->lock = 0; } while (0)
-#define spin_lock_irq(x)	do { cli(); spin_lock(x); } while (0)
-#define spin_unlock_irq(x)	do { spin_unlock(x); sti(); } while (0)
-
-#define spin_lock_irqsave(x, flags) \
-	do { save_flags(flags); spin_lock_irq(x); } while (0)
-#define spin_unlock_irqrestore(x, flags) \
-	do { spin_unlock(x); restore_flags(flags); } while (0)
X 
X #else /* (DEBUG_SPINLOCKS >= 2) */
X 
@@ -71,11 +86,6 @@
X #define spin_lock(x)		do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
X #define spin_unlock_wait(x)	do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
X #define spin_unlock(x)		do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
-#define spin_lock_irq(x)	do {cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
-#define spin_unlock_irq(x)	do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; sti();} while (0)
-
-#define spin_lock_irqsave(x,flags)      do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
-#define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
X 
X #endif	/* DEBUG_SPINLOCKS */
X 
@@ -103,19 +113,6 @@
X #define read_unlock(lock)	do { } while(0)
X #define write_lock(lock)	do { } while(0)
X #define write_unlock(lock)	do { } while(0)
-#define read_lock_irq(lock)	cli()
-#define read_unlock_irq(lock)	sti()
-#define write_lock_irq(lock)	cli()
-#define write_unlock_irq(lock)	sti()
-
-#define read_lock_irqsave(lock, flags)	\
-	do { save_flags(flags); cli(); } while (0)
-#define read_unlock_irqrestore(lock, flags) \
-	restore_flags(flags)
-#define write_lock_irqsave(lock, flags)	\
-	do { save_flags(flags); cli(); } while (0)
-#define write_unlock_irqrestore(lock, flags) \
-	restore_flags(flags)
X 
X #else	/* __SMP__ */
X 
@@ -168,18 +165,6 @@
X 
X #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
X 
-#define spin_lock_irq(lock) \
-	do { __cli(); spin_lock(lock); } while (0)
-
-#define spin_unlock_irq(lock) \
-	do { spin_unlock(lock); __sti(); } while (0)
-
-#define spin_lock_irqsave(lock, flags) \
-	do { __save_flags(flags); __cli(); spin_lock(lock); } while (0)
-
-#define spin_unlock_irqrestore(lock, flags) \
-	do { spin_unlock(lock); __restore_flags(flags); } while (0)
-
X /*
X  * Read-write spinlocks, allowing multiple readers
X  * but only one writer.
@@ -235,20 +220,6 @@
X 
X #define write_unlock(rw) \
X 	asm volatile("lock ; btrl $31,%0":"=m" (__dummy_lock(&(rw)->lock)))
-
-#define read_lock_irq(lock)	do { __cli(); read_lock(lock); } while (0)
-#define read_unlock_irq(lock)	do { read_unlock(lock); __sti(); } while (0)
-#define write_lock_irq(lock)	do { __cli(); write_lock(lock); } while (0)
-#define write_unlock_irq(lock)	do { write_unlock(lock); __sti(); } while (0)
-
-#define read_lock_irqsave(lock, flags)	\
-	do { __save_flags(flags); __cli(); read_lock(lock); } while (0)
-#define read_unlock_irqrestore(lock, flags) \
-	do { read_unlock(lock); __restore_flags(flags); } while (0)
-#define write_lock_irqsave(lock, flags)	\
-	do { __save_flags(flags); __cli(); write_lock(lock); } while (0)
-#define write_unlock_irqrestore(lock, flags) \
-	do { write_unlock(lock); __restore_flags(flags); } while (0)
X 
X #endif /* __SMP__ */
X #endif /* __ASM_SPINLOCK_H */
diff -u --recursive --new-file v2.3.3/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.3.3/linux/include/asm-i386/system.h	Tue May 11 13:03:58 1999
+++ linux/include/asm-i386/system.h	Tue May 25 14:56:58 1999
@@ -181,6 +181,11 @@
X #define __restore_flags(x) \
X __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
X 
+/* For spinlocks etc */
+#define local_irq_save(x)	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
+#define local_irq_restore(x)	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#define local_irq_disable()	__asm__ __volatile__("cli": : :"memory")
+#define local_irq_enable()	__asm__ __volatile__("sti": : :"memory")
X 
X #ifdef __SMP__
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.3.3/linux/include/asm-m68k/processor.h	Tue Jan 19 10:58:34 1999
+++ linux/include/asm-m68k/processor.h	Tue May 25 14:55:05 1999
@@ -7,6 +7,12 @@
X #ifndef __ASM_M68K_PROCESSOR_H
X #define __ASM_M68K_PROCESSOR_H
X 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
X #include <asm/segment.h>
X #include <asm/fpu.h>
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.3.3/linux/include/asm-mips/processor.h	Mon Jan 18 09:55:30 1999
+++ linux/include/asm-mips/processor.h	Tue May 25 14:55:05 1999
@@ -11,6 +11,12 @@
X #ifndef __ASM_MIPS_PROCESSOR_H
X #define __ASM_MIPS_PROCESSOR_H
X 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
X #if !defined (_LANGUAGE_ASSEMBLY)
X #include <asm/cachectl.h>
X #include <asm/mipsregs.h>
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.3.3/linux/include/asm-ppc/ide.h	Fri May 14 18:55:28 1999
+++ linux/include/asm-ppc/ide.h	Sat May 22 13:03:00 1999
@@ -83,12 +83,18 @@
X 
X static __inline__ int ide_default_irq(ide_ioreg_t base)
X {
-	return ppc_ide_md.default_irq(base);
+	if ( ppc_ide_md.default_irq )
+		return ppc_ide_md.default_irq(base);
+	else
+		return -1;
X }
X 
X static __inline__ ide_ioreg_t ide_default_io_base(int index)
X {
-	return ppc_ide_md.default_io_base(index);
+	if ( ppc_ide_md.default_io_base )
+		return ppc_ide_md.default_io_base(index);
+	else
+		return -1;
X }
X 
X static __inline__ void ide_init_default_hwifs(void)
@@ -107,21 +113,28 @@
X 
X static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
X {
-	return ppc_ide_md.check_region(from, extent);
+	if ( ppc_ide_md.check_region )
+		return ppc_ide_md.check_region(from, extent);
+	else
+		return -1;
X }
X 
X static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
X {
-	ppc_ide_md.request_region(from, extent, name);
+	if ( ppc_ide_md.request_region )
+		ppc_ide_md.request_region(from, extent, name);
X }
X 
X static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
X {
-	ppc_ide_md.release_region(from, extent);
+	if ( ppc_ide_md.release_region )
+		ppc_ide_md.release_region(from, extent);
X }
X 
-static __inline__ void ide_fix_driveid (struct hd_driveid *id) {
-        ppc_ide_md.fix_driveid(id);
+static __inline__ void ide_fix_driveid (struct hd_driveid *id)
+{
+        if ( ppc_ide_md.fix_driveid )
+		ppc_ide_md.fix_driveid(id);
X }
X 
X #undef inb
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h
--- v2.3.3/linux/include/asm-ppc/mmu.h	Fri Mar 19 10:50:09 1999
+++ linux/include/asm-ppc/mmu.h	Wed May 26 16:55:40 1999
@@ -5,14 +5,25 @@
X #ifndef _PPC_MMU_H_
X #define _PPC_MMU_H_
X 
+#include <linux/config.h>
+
X #ifndef __ASSEMBLY__
X /* Hardware Page Table Entry */
X typedef struct _PTE {
+#ifdef CONFIG_PPC64
+	unsigned long long vsid:52;
+	unsigned long api:5;
+	unsigned long :5;
+	unsigned long h:1;
+	unsigned long v:1;
+	unsigned long long rpn:52;
+#else /* CONFIG_PPC64 */
X 	unsigned long v:1;	/* Entry is valid */
X 	unsigned long vsid:24;	/* Virtual segment identifier */
X 	unsigned long h:1;	/* Hash algorithm indicator */
X 	unsigned long api:6;	/* Abbreviated page index */
X 	unsigned long rpn:20;	/* Real (physical) page number */
+#endif /* CONFIG_PPC64 */
X 	unsigned long    :3;	/* Unused */
X 	unsigned long r:1;	/* Referenced */
X 	unsigned long c:1;	/* Changed */
@@ -53,7 +64,11 @@
X } P601_BATU;
X 
X typedef struct _BATU {		/* Upper part of BAT (all except 601) */
+#ifdef CONFIG_PPC64
+	unsigned long long bepi:47;
+#else /* CONFIG_PPC64 */
X 	unsigned long bepi:15;	/* Effective page index (virtual address) */
+#endif /* CONFIG_PPC64 */
X 	unsigned long :4;	/* Unused */
X 	unsigned long bl:11;	/* Block size mask */
X 	unsigned long vs:1;	/* Supervisor valid */
@@ -68,7 +83,11 @@
X } P601_BATL;
X 
X typedef struct _BATL {		/* Lower part of BAT (all except 601) */
+#ifdef CONFIG_PPC64
+	unsigned long long brpn:47;
+#else /* CONFIG_PPC64 */
X 	unsigned long brpn:15;	/* Real page index (physical address) */
+#endif /* CONFIG_PPC64 */
X 	unsigned long :10;	/* Unused */
X 	unsigned long w:1;	/* Write-thru cache */
X 	unsigned long i:1;	/* Cache inhibit */
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.3.3/linux/include/asm-ppc/pgtable.h	Thu Apr 29 12:39:01 1999
+++ linux/include/asm-ppc/pgtable.h	Sat May 22 13:03:00 1999
@@ -20,6 +20,11 @@
X #define flush_tlb_page local_flush_tlb_page
X #define flush_tlb_range local_flush_tlb_range
X 
+extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+	/* PPC has hw page tables. */
+}
+
X /*
X  * No cache flushing is required when address mappings are
X  * changed, because the caches on PowerPCs are physically
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.3.3/linux/include/asm-ppc/processor.h	Tue May 11 08:24:32 1999
+++ linux/include/asm-ppc/processor.h	Tue May 25 14:55:05 1999
@@ -1,12 +1,22 @@
X #ifndef __ASM_PPC_PROCESSOR_H
X #define __ASM_PPC_PROCESSOR_H
X 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
X #include <linux/config.h>
X 
X #include <asm/ptrace.h>
X #include <asm/residual.h>
X 
X /* Bit encodings for Machine State Register (MSR) */
+#ifdef CONFIG_PPC64
+#define MSR_SF		(1<<63)
+#define MSR_ISF		(1<<61)
+#endif /* CONFIG_PPC64 */
X #define MSR_POW		(1<<18)		/* Enable Power Management */
X #define MSR_TGPR	(1<<17)		/* TLB Update registers in use */
X #define MSR_ILE		(1<<16)		/* Interrupt Little-Endian enable */
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/ptrace.h linux/include/asm-ppc/ptrace.h
--- v2.3.3/linux/include/asm-ppc/ptrace.h	Tue Apr 14 17:34:00 1998
+++ linux/include/asm-ppc/ptrace.h	Wed May 26 16:55:40 1999
@@ -17,22 +17,29 @@
X  * the PT_* values below.  This simplifies arch/ppc/kernel/ptrace.c.
X  */
X 
+#include <linux/config.h>
+
X #ifndef __ASSEMBLY__
+#ifdef CONFIG_PPC64
+#define REG unsigned long /*long*/
+#else
+#define REG unsigned long
+#endif
X struct pt_regs {
-	unsigned long gpr[32];
-	unsigned long nip;
-	unsigned long msr;
-	unsigned long orig_gpr3; /* Used for restarting system calls */
-	unsigned long ctr;
-	unsigned long link;
-	unsigned long xer;
-	unsigned long ccr;
-	unsigned long mq;	/* 601 only (not used at present) */
-				/* Used on APUS to hold IPL value. */
-	unsigned long trap;	/* Reason for being here */
-	unsigned long dar;	/* Fault registers */
-	unsigned long dsisr;
-	unsigned long result;   /* Result of a system call */
+	REG gpr[32];
+	REG nip;
+	REG msr;
+	REG orig_gpr3;	/* Used for restarting system calls */
+	REG ctr;
+	REG link;
+	REG xer;
+	REG ccr;
+	REG mq;		/* 601 only (not used at present) */
+			/* Used on APUS to hold IPL value. */
+	REG trap;	/* Reason for being here */
+	REG dar;	/* Fault registers */
+	REG dsisr;
+	REG result;   	/* Result of a system call */
X };
X #endif
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- v2.3.3/linux/include/asm-ppc/semaphore.h	Mon May 17 09:55:23 1999
+++ linux/include/asm-ppc/semaphore.h	Sat May 22 13:03:00 1999
@@ -1,27 +1,64 @@
-#ifndef _PPC_SEMAPHORE_H
-#define _PPC_SEMAPHORE_H
+#ifndef _SPARC_SEMAPHORE_H
+#define _SPARC_SEMAPHORE_H
X 
X /*
- * SMP- and interrupt-safe semaphores..
- *
- * (C) Copyright 1996 Linus Torvalds
- * Adapted for PowerPC by Gary Thomas and Paul Mackerras
+ * Swiped from asm-sparc/semaphore.h and modified
+ * -- Cort (co...@cs.nmt.edu)
X  */
X 
+#ifdef __KERNEL__
+
X #include <asm/atomic.h>
+#include <linux/wait.h>
X 
X struct semaphore {
X 	atomic_t count;
X 	atomic_t waking;
X 	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
X };
X 
-#define sema_init(sem, val)	atomic_set(&((sem)->count), (val))
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+		, (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+	atomic_set(&sem->count, val);
+	atomic_set(&sem->waking, 0);
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
X 
-#define MUTEX		((struct semaphore) \
-			 { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED	((struct semaphore) \
-			 { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
X 
X extern void __down(struct semaphore * sem);
X extern int  __down_interruptible(struct semaphore * sem);
@@ -65,4 +102,6 @@
X 		__up(sem);
X }	
X 
-#endif /* !(_PPC_SEMAPHORE_H) */
+#endif /* __KERNEL__ */
+
+#endif /* !(_SPARC_SEMAPHORE_H) */
diff -u --recursive --new-file v2.3.3/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- v2.3.3/linux/include/asm-ppc/system.h	Tue May 11 08:24:32 1999
+++ linux/include/asm-ppc/system.h	Sat May 22 13:03:00 1999
@@ -58,7 +58,6 @@
X extern int _disable_interrupts(void);
X extern void _enable_interrupts(int);
X 
-extern void instruction_dump(unsigned long *);
X extern void print_backtrace(unsigned long *);
X extern void show_regs(struct pt_regs * regs);
X extern void flush_instruction_cache(void);
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v2.3.3/linux/include/asm-sparc/pgtable.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/pgtable.h	Thu May 27 09:55:21 1999
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.78 1999/01/07 14:14:05 jj Exp $ */
+/* $Id: pgtable.h,v 1.80 1999/05/27 04:52:40 davem Exp $ */
X #ifndef _SPARC_PGTABLE_H
X #define _SPARC_PGTABLE_H
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.3.3/linux/include/asm-sparc/processor.h	Thu Mar 25 09:23:34 1999
+++ linux/include/asm-sparc/processor.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.70 1999/03/24 11:42:44 davem Exp $
+/* $Id: processor.h,v 1.71 1999/05/27 04:52:43 davem Exp $
X  * include/asm-sparc/processor.h
X  *
X  * Copyright (C) 1994 David S. Miller (da...@caip.rutgers.edu)
@@ -6,6 +6,12 @@
X 
X #ifndef __ASM_SPARC_PROCESSOR_H
X #define __ASM_SPARC_PROCESSOR_H
+
+/*
+ * Sparc32 implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
X 
X #include <linux/a.out.h>
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h
--- v2.3.3/linux/include/asm-sparc/softirq.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc/softirq.h	Thu May 27 09:55:22 1999
@@ -103,7 +103,8 @@
X static inline int softirq_trylock(int cpu)
X {
X 	if (spin_trylock(&global_bh_count)) {
-		if (atomic_read(&global_bh_lock) == 0) {
+		if (atomic_read(&global_bh_lock) == 0 &&
+		    local_bh_count[cpu] == 0) {
X 			++local_bh_count[cpu];
X 			return 1;
X 		}
@@ -118,6 +119,9 @@
X 	spin_unlock(&global_bh_count);
X }
X 
+#define local_bh_disable()	(local_bh_count[smp_processor_id()]++)
+#define local_bh_enable()	(local_bh_count[smp_processor_id()]--)
+
X #else
X extern unsigned int local_bh_count;
X 
@@ -128,6 +132,9 @@
X #define softirq_trylock(cpu)	(local_bh_count ? 0 : (local_bh_count=1))
X #define softirq_endlock(cpu)	(local_bh_count = 0)
X #define synchronize_bh()	barrier()
+
+#define local_bh_disable()	(local_bh_count++)
+#define local_bh_enable()	(local_bh_count--)
X 
X /*
X  * These use a mask count to correctly handle
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h
--- v2.3.3/linux/include/asm-sparc/spinlock.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc/spinlock.h	Thu May 27 09:55:22 1999
@@ -22,6 +22,8 @@
X #define spin_unlock(lock)	do { } while(0)
X #define spin_lock_irq(lock)	cli()
X #define spin_unlock_irq(lock)	sti()
+#define spin_lock_bh(lock)	local_bh_disable()
+#define spin_unlock_bh(lock)	local_bh_enable()
X 
X #define spin_lock_irqsave(lock, flags)		save_and_cli(flags)
X #define spin_unlock_irqrestore(lock, flags)	restore_flags(flags)
@@ -47,6 +49,10 @@
X #define read_unlock_irq(lock)	sti()
X #define write_lock_irq(lock)	cli()
X #define write_unlock_irq(lock)	sti()
+#define read_lock_bh(lock)	local_bh_disable()
+#define read_unlock_bh(lock)	local_bh_enable()
+#define write_lock_bh(lock)	local_bh_disable()
+#define write_unlock_bh(lock)	local_bh_enable()
X 
X #define read_lock_irqsave(lock, flags)		save_and_cli(flags)
X #define read_unlock_irqrestore(lock, flags)	restore_flags(flags)
@@ -80,10 +86,12 @@
X 
X #define spin_lock(lock)		_do_spin_lock(lock, "spin_lock")
X #define spin_lock_irq(lock)	do { __cli(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
+#define spin_lock_bh(lock)	do { local_bh_disable(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
X #define spin_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_spin_lock(lock, "spin_lock_irqsave"); } while(0)
X 
X #define spin_unlock(lock)	_do_spin_unlock(lock)
X #define spin_unlock_irq(lock)	do { _do_spin_unlock(lock); __sti(); } while(0)
+#define spin_unlock_bh(lock)	do { _do_spin_unlock(lock); local_bh_enable(); } while(0)
X #define spin_unlock_irqrestore(lock, flags) do { _do_spin_unlock(lock); __restore_flags(flags); } while(0)
X 
X struct _rwlock_debug {
@@ -107,6 +115,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define read_lock_irq(lock)	do { __cli(); _do_read_lock(lock, "read_lock_irq"); } while(0)
+#define read_lock_bh(lock)	do { local_bh_disable(); _do_read_lock(lock, "read_lock_irq"); } while(0)
X #define read_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_read_lock(lock, "read_lock_irqsave"); } while(0)
X 
X #define read_unlock(lock) \
@@ -116,6 +125,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define read_unlock_irq(lock)	do { _do_read_unlock(lock, "read_unlock_irq"); __sti(); } while(0)
+#define read_unlock_bh(lock)	do { _do_read_unlock(lock, "read_unlock_irq"); local_bh_enable(); } while(0)
X #define read_unlock_irqrestore(lock, flags) do { _do_read_unlock(lock, "read_unlock_irqrestore"); __restore_flags(flags); } while(0)
X 
X #define write_lock(lock) \
@@ -125,6 +135,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define write_lock_irq(lock)	do { __cli(); _do_write_lock(lock, "write_lock_irq"); } while(0)
+#define write_lock_bh(lock)	do { local_bh_disable(); _do_write_lock(lock, "write_lock_irq"); } while(0)
X #define write_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_write_lock(lock, "write_lock_irqsave"); } while(0)
X 
X #define write_unlock(lock) \
@@ -134,6 +145,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define write_unlock_irq(lock)	do { _do_write_unlock(lock); __sti(); } while(0)
+#define write_unlock_bh(lock)	do { _do_write_unlock(lock); local_bh_enable(); } while(0)
X #define write_unlock_irqrestore(lock, flags) do { _do_write_unlock(lock); __restore_flags(flags); } while(0)
X 
X #else /* !SPIN_LOCK_DEBUG */
@@ -200,6 +212,8 @@
X 	: "g2", "memory", "cc");
X }
X 
+#define spin_lock_bh(___lk) do { local_bh_disable(); spin_lock(___lk); } while(0)
+
X extern __inline__ void spin_unlock_irq(spinlock_t *lock)
X {
X 	__asm__ __volatile__("
@@ -213,6 +227,8 @@
X 	: "g2", "memory");
X }
X 
+#define spin_unlock_bh(___lk) do { spin_unlock(___lk); local_bh_enable(); } while(0)
+
X #define spin_lock_irqsave(__lock, flags)	\
X do {						\
X 	register spinlock_t *__lp asm("g1");	\
@@ -338,6 +354,11 @@
X #define read_unlock_irq(lock)	do { _read_unlock(lock); __sti(); } while (0)
X #define write_lock_irq(lock)	do { __cli(); write_lock(lock); } while (0)
X #define write_unlock_irq(lock)	do { write_unlock(lock); __sti(); } while (0)
+
+#define read_lock_bh(lock)	do { local_bh_disable(); _read_lock(lock); } while (0)
+#define read_unlock_bh(lock)	do { _read_unlock(lock); local_bh_enable(); } while (0)
+#define write_lock_bh(lock)	do { local_bh_disable(); write_lock(lock); } while (0)
+#define write_unlock_bh(lock)	do { write_unlock(lock); local_bh_enable(); } while (0)
X 
X #define read_lock_irqsave(lock, flags)	\
X 	do { __save_and_cli(flags); _read_lock(lock); } while (0)
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.3.3/linux/include/asm-sparc64/asm_offsets.h	Fri May 14 18:55:28 1999
+++ linux/include/asm-sparc64/asm_offsets.h	Thu May 27 09:55:22 1999
@@ -12,177 +12,177 @@
X #define ASIZ_task_flags	0x00000008
X #define AOFF_task_sigpending	0x00000010
X #define ASIZ_task_sigpending	0x00000004
-#define AOFF_task_addr_limit	0x00000018
-#define ASIZ_task_addr_limit	0x00000008
-#define AOFF_task_exec_domain	0x00000020
+#define AOFF_task_addr_limit	0x00000014
+#define ASIZ_task_addr_limit	0x00000001
+#define AOFF_task_exec_domain	0x00000018
X #define ASIZ_task_exec_domain	0x00000008
-#define AOFF_task_need_resched	0x00000028
+#define AOFF_task_need_resched	0x00000020
X #define ASIZ_task_need_resched	0x00000008
-#define AOFF_task_counter	0x00000030
+#define AOFF_task_counter	0x00000028
X #define ASIZ_task_counter	0x00000008
-#define AOFF_task_priority	0x00000038
+#define AOFF_task_priority	0x00000030
X #define ASIZ_task_priority	0x00000008
-#define AOFF_task_avg_slice	0x00000040
+#define AOFF_task_avg_slice	0x00000038
X #define ASIZ_task_avg_slice	0x00000008
-#define AOFF_task_has_cpu	0x00000048
+#define AOFF_task_has_cpu	0x00000040
X #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x0000004c
+#define AOFF_task_processor	0x00000044
X #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000050
+#define AOFF_task_last_processor	0x00000048
X #define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x00000054
+#define AOFF_task_lock_depth	0x0000004c
X #define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000058
+#define AOFF_task_next_task	0x00000050
X #define ASIZ_task_next_task	0x00000008
-#define AOFF_task_prev_task	0x00000060
+#define AOFF_task_prev_task	0x00000058
X #define ASIZ_task_prev_task	0x00000008
-#define AOFF_task_next_run	0x00000068
+#define AOFF_task_next_run	0x00000060
X #define ASIZ_task_next_run	0x00000008
-#define AOFF_task_prev_run	0x00000070
+#define AOFF_task_prev_run	0x00000068
X #define ASIZ_task_prev_run	0x00000008
-#define AOFF_task_binfmt	0x00000078
+#define AOFF_task_binfmt	0x00000070
X #define ASIZ_task_binfmt	0x00000008
-#define AOFF_task_exit_code	0x00000080
+#define AOFF_task_exit_code	0x00000078
X #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x00000084
+#define AOFF_task_exit_signal	0x0000007c
X #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000088
+#define AOFF_task_pdeath_signal	0x00000080
X #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000090
+#define AOFF_task_personality	0x00000088
X #define ASIZ_task_personality	0x00000008
-#define AOFF_task_pid	0x0000009c
+#define AOFF_task_pid	0x00000094
X #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x000000a0
+#define AOFF_task_pgrp	0x00000098
X #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x000000a4
+#define AOFF_task_tty_old_pgrp	0x0000009c
X #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x000000a8
+#define AOFF_task_session	0x000000a0
X #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x000000ac
+#define AOFF_task_leader	0x000000a4
X #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x000000b0
+#define AOFF_task_p_opptr	0x000000a8
X #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x000000b8
+#define AOFF_task_p_pptr	0x000000b0
X #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x000000c0
+#define AOFF_task_p_cptr	0x000000b8
X #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x000000c8
+#define AOFF_task_p_ysptr	0x000000c0
X #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x000000d0
+#define AOFF_task_p_osptr	0x000000c8
X #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x000000d8
+#define AOFF_task_pidhash_next	0x000000d0
X #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x000000e0
+#define AOFF_task_pidhash_pprev	0x000000d8
X #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_tarray_ptr	0x000000e8
+#define AOFF_task_tarray_ptr	0x000000e0
X #define ASIZ_task_tarray_ptr	0x00000008
-#define AOFF_task_wait_chldexit	0x000000f0
+#define AOFF_task_wait_chldexit	0x000000e8
X #define ASIZ_task_wait_chldexit	0x00000028
-#define AOFF_task_vfork_sem	0x00000118
+#define AOFF_task_vfork_sem	0x00000110
X #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000120
+#define AOFF_task_policy	0x00000118
X #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000128
+#define AOFF_task_rt_priority	0x00000120
X #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000130
+#define AOFF_task_it_real_value	0x00000128
X #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000138
+#define AOFF_task_it_prof_value	0x00000130
X #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000140
+#define AOFF_task_it_virt_value	0x00000138
X #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000148
+#define AOFF_task_it_real_incr	0x00000140
X #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000150
+#define AOFF_task_it_prof_incr	0x00000148
X #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000158
+#define AOFF_task_it_virt_incr	0x00000150
X #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000160
+#define AOFF_task_real_timer	0x00000158
X #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000188
+#define AOFF_task_times	0x00000180
X #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x000001a8
+#define AOFF_task_start_time	0x000001a0
X #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x000001b0
+#define AOFF_task_per_cpu_utime	0x000001a8
X #define ASIZ_task_per_cpu_utime	0x00000008
-#define AOFF_task_min_flt	0x000001c0
+#define AOFF_task_min_flt	0x000001b8
X #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000001c8
+#define AOFF_task_maj_flt	0x000001c0
X #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000001d0
+#define AOFF_task_nswap	0x000001c8
X #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000001d8
+#define AOFF_task_cmin_flt	0x000001d0
X #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000001e0
+#define AOFF_task_cmaj_flt	0x000001d8
X #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000001e8
+#define AOFF_task_cnswap	0x000001e0
X #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000001f4
+#define AOFF_task_uid	0x000001ec
X #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000001f8
+#define AOFF_task_euid	0x000001f0
X #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000001fc
+#define AOFF_task_suid	0x000001f4
X #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x00000200
+#define AOFF_task_fsuid	0x000001f8
X #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x00000204
+#define AOFF_task_gid	0x000001fc
X #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x00000208
+#define AOFF_task_egid	0x00000200
X #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x0000020c
+#define AOFF_task_sgid	0x00000204
X #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x00000210
+#define AOFF_task_fsgid	0x00000208
X #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x00000214
+#define AOFF_task_ngroups	0x0000020c
X #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000218
+#define AOFF_task_groups	0x00000210
X #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000298
+#define AOFF_task_cap_effective	0x00000290
X #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000029c
+#define AOFF_task_cap_inheritable	0x00000294
X #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x000002a0
+#define AOFF_task_cap_permitted	0x00000298
X #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x000002a8
+#define AOFF_task_user	0x000002a0
X #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x000002b0
+#define AOFF_task_rlim	0x000002a8
X #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000350
+#define AOFF_task_used_math	0x00000348
X #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000352
+#define AOFF_task_comm	0x0000034a
X #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000364
+#define AOFF_task_link_count	0x0000035c
X #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000368
+#define AOFF_task_tty	0x00000360
X #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000370
+#define AOFF_task_semundo	0x00000368
X #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000378
+#define AOFF_task_semsleeping	0x00000370
X #define ASIZ_task_semsleeping	0x00000008
X #define AOFF_task_tss	0x00000380
-#define ASIZ_task_tss	0x00000470
-#define AOFF_task_fs	0x000007f0
+#define ASIZ_task_tss	0x00000460
+#define AOFF_task_fs	0x000007e0
X #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000007f8
+#define AOFF_task_files	0x000007e8
X #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x00000800
+#define AOFF_task_mm	0x000007f0
X #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x00000808
+#define AOFF_task_sigmask_lock	0x000007f8
X #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x00000810
+#define AOFF_task_sig	0x00000800
X #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x00000818
+#define AOFF_task_signal	0x00000808
X #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000820
+#define AOFF_task_blocked	0x00000810
X #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000828
+#define AOFF_task_sigqueue	0x00000818
X #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000830
+#define AOFF_task_sigqueue_tail	0x00000820
X #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000838
+#define AOFF_task_sas_ss_sp	0x00000828
X #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000840
+#define AOFF_task_sas_ss_size	0x00000830
X #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000850
+#define ASIZ_task	0x00000840
X #define AOFF_mm_mmap	0x00000000
X #define ASIZ_mm_mmap	0x00000008
X #define AOFF_mm_mmap_avl	0x00000008
@@ -246,47 +246,45 @@
X #define ASIZ_thread_cwp	0x00000002
X #define AOFF_thread_flags	0x0000000c
X #define ASIZ_thread_flags	0x00000002
-#define AOFF_thread_ctx	0x0000000e
-#define ASIZ_thread_ctx	0x00000002
+#define AOFF_thread_current_ds	0x0000000e
+#define ASIZ_thread_current_ds	0x00000001
X #define AOFF_thread_w_saved	0x00000010
X #define ASIZ_thread_w_saved	0x00000002
X #define AOFF_thread_new_signal	0x00000012
X #define ASIZ_thread_new_signal	0x00000002
-#define AOFF_thread____pad	0x00000014
-#define ASIZ_thread____pad	0x00000004
-#define AOFF_thread_current_ds	0x00000018
-#define ASIZ_thread_current_ds	0x00000008
-#define AOFF_thread_kregs	0x00000020
+#define AOFF_thread_ctx	0x00000014
+#define ASIZ_thread_ctx	0x00000002
+#define AOFF_thread_kregs	0x00000018
X #define ASIZ_thread_kregs	0x00000008
-#define AOFF_thread_utraps	0x00000028
+#define AOFF_thread_utraps	0x00000020
X #define ASIZ_thread_utraps	0x00000008
-#define AOFF_thread_reg_window	0x00000030
+#define AOFF_thread_fpdepth	0x00000028
+#define ASIZ_thread_fpdepth	0x00000001
+#define AOFF_thread_fpsaved	0x00000029
+#define ASIZ_thread_fpsaved	0x00000007
+#define AOFF_thread_gsr	0x00000030
+#define ASIZ_thread_gsr	0x00000007
+#define AOFF_thread_xfsr	0x00000038
+#define ASIZ_thread_xfsr	0x00000038
+#define AOFF_thread_reg_window	0x00000070
X #define ASIZ_thread_reg_window	0x00000380
-#define AOFF_thread_rwbuf_stkptrs	0x000003b0
+#define AOFF_thread_rwbuf_stkptrs	0x000003f0
X #define ASIZ_thread_rwbuf_stkptrs	0x00000038
-#define AOFF_thread_sig_address	0x000003e8
+#define AOFF_thread_sig_address	0x00000428
X #define ASIZ_thread_sig_address	0x00000008
-#define AOFF_thread_sig_desc	0x000003f0
+#define AOFF_thread_sig_desc	0x00000430
X #define ASIZ_thread_sig_desc	0x00000008
-#define AOFF_thread_user_cntd0	0x000003f8
+#define AOFF_thread_user_cntd0	0x00000438
X #define ASIZ_thread_user_cntd0	0x00000008
-#define AOFF_thread_user_cntd1	0x00000400
+#define AOFF_thread_user_cntd1	0x00000440
X #define ASIZ_thread_user_cntd1	0x00000008
-#define AOFF_thread_kernel_cntd0	0x00000408
+#define AOFF_thread_kernel_cntd0	0x00000448
X #define ASIZ_thread_kernel_cntd0	0x00000008
-#define AOFF_thread_kernel_cntd1	0x00000410
+#define AOFF_thread_kernel_cntd1	0x00000450
X #define ASIZ_thread_kernel_cntd1	0x00000008
-#define AOFF_thread_pcr_reg	0x00000418
+#define AOFF_thread_pcr_reg	0x00000458
X #define ASIZ_thread_pcr_reg	0x00000008
-#define AOFF_thread_fpdepth	0x00000420
-#define ASIZ_thread_fpdepth	0x00000001
-#define AOFF_thread_fpsaved	0x00000421
-#define ASIZ_thread_fpsaved	0x00000007
-#define AOFF_thread_gsr	0x00000428
-#define ASIZ_thread_gsr	0x00000007
-#define AOFF_thread_xfsr	0x00000430
-#define ASIZ_thread_xfsr	0x00000038
-#define ASIZ_thread	0x00000470
+#define ASIZ_thread	0x00000460
X 
X #else /* CONFIG_SMP */
X 
@@ -298,177 +296,177 @@
X #define ASIZ_task_flags	0x00000008
X #define AOFF_task_sigpending	0x00000010
X #define ASIZ_task_sigpending	0x00000004
-#define AOFF_task_addr_limit	0x00000018
-#define ASIZ_task_addr_limit	0x00000008
-#define AOFF_task_exec_domain	0x00000020
+#define AOFF_task_addr_limit	0x00000014
+#define ASIZ_task_addr_limit	0x00000001
+#define AOFF_task_exec_domain	0x00000018
X #define ASIZ_task_exec_domain	0x00000008
-#define AOFF_task_need_resched	0x00000028
+#define AOFF_task_need_resched	0x00000020
X #define ASIZ_task_need_resched	0x00000008
-#define AOFF_task_counter	0x00000030
+#define AOFF_task_counter	0x00000028
X #define ASIZ_task_counter	0x00000008
-#define AOFF_task_priority	0x00000038
+#define AOFF_task_priority	0x00000030
X #define ASIZ_task_priority	0x00000008
-#define AOFF_task_avg_slice	0x00000040
+#define AOFF_task_avg_slice	0x00000038
X #define ASIZ_task_avg_slice	0x00000008
-#define AOFF_task_has_cpu	0x00000048
+#define AOFF_task_has_cpu	0x00000040
X #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x0000004c
+#define AOFF_task_processor	0x00000044
X #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000050
+#define AOFF_task_last_processor	0x00000048
X #define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x00000054
+#define AOFF_task_lock_depth	0x0000004c
X #define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000058
+#define AOFF_task_next_task	0x00000050
X #define ASIZ_task_next_task	0x00000008
-#define AOFF_task_prev_task	0x00000060
+#define AOFF_task_prev_task	0x00000058
X #define ASIZ_task_prev_task	0x00000008
-#define AOFF_task_next_run	0x00000068
+#define AOFF_task_next_run	0x00000060
X #define ASIZ_task_next_run	0x00000008
-#define AOFF_task_prev_run	0x00000070
+#define AOFF_task_prev_run	0x00000068
X #define ASIZ_task_prev_run	0x00000008
-#define AOFF_task_binfmt	0x00000078
+#define AOFF_task_binfmt	0x00000070
X #define ASIZ_task_binfmt	0x00000008
-#define AOFF_task_exit_code	0x00000080
+#define AOFF_task_exit_code	0x00000078
X #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x00000084
+#define AOFF_task_exit_signal	0x0000007c
X #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000088
+#define AOFF_task_pdeath_signal	0x00000080
X #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000090
+#define AOFF_task_personality	0x00000088
X #define ASIZ_task_personality	0x00000008
-#define AOFF_task_pid	0x0000009c
+#define AOFF_task_pid	0x00000094
X #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x000000a0
+#define AOFF_task_pgrp	0x00000098
X #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x000000a4
+#define AOFF_task_tty_old_pgrp	0x0000009c
X #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x000000a8
+#define AOFF_task_session	0x000000a0
X #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x000000ac
+#define AOFF_task_leader	0x000000a4
X #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x000000b0
+#define AOFF_task_p_opptr	0x000000a8
X #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x000000b8
+#define AOFF_task_p_pptr	0x000000b0
X #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x000000c0
+#define AOFF_task_p_cptr	0x000000b8
X #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x000000c8
+#define AOFF_task_p_ysptr	0x000000c0
X #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x000000d0
+#define AOFF_task_p_osptr	0x000000c8
X #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x000000d8
+#define AOFF_task_pidhash_next	0x000000d0
X #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x000000e0
+#define AOFF_task_pidhash_pprev	0x000000d8
X #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_tarray_ptr	0x000000e8
+#define AOFF_task_tarray_ptr	0x000000e0
X #define ASIZ_task_tarray_ptr	0x00000008
-#define AOFF_task_wait_chldexit	0x000000f0
+#define AOFF_task_wait_chldexit	0x000000e8
X #define ASIZ_task_wait_chldexit	0x00000028
-#define AOFF_task_vfork_sem	0x00000118
+#define AOFF_task_vfork_sem	0x00000110
X #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000120
+#define AOFF_task_policy	0x00000118
X #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000128
+#define AOFF_task_rt_priority	0x00000120
X #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000130
+#define AOFF_task_it_real_value	0x00000128
X #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000138
+#define AOFF_task_it_prof_value	0x00000130
X #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000140
+#define AOFF_task_it_virt_value	0x00000138
X #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000148
+#define AOFF_task_it_real_incr	0x00000140
X #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000150
+#define AOFF_task_it_prof_incr	0x00000148
X #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000158
+#define AOFF_task_it_virt_incr	0x00000150
X #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000160
+#define AOFF_task_real_timer	0x00000158
X #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000188
+#define AOFF_task_times	0x00000180
X #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x000001a8
+#define AOFF_task_start_time	0x000001a0
X #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x000001b0
+#define AOFF_task_per_cpu_utime	0x000001a8
X #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x000003b0
+#define AOFF_task_min_flt	0x000003a8
X #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000003b8
+#define AOFF_task_maj_flt	0x000003b0
X #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000003c0
+#define AOFF_task_nswap	0x000003b8
X #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000003c8
+#define AOFF_task_cmin_flt	0x000003c0
X #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000003d0
+#define AOFF_task_cmaj_flt	0x000003c8
X #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000003d8
+#define AOFF_task_cnswap	0x000003d0
X #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000003e4
+#define AOFF_task_uid	0x000003dc
X #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000003e8
+#define AOFF_task_euid	0x000003e0
X #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000003ec
+#define AOFF_task_suid	0x000003e4
X #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000003f0
+#define AOFF_task_fsuid	0x000003e8
X #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000003f4
+#define AOFF_task_gid	0x000003ec
X #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000003f8
+#define AOFF_task_egid	0x000003f0
X #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000003fc
+#define AOFF_task_sgid	0x000003f4
X #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x00000400
+#define AOFF_task_fsgid	0x000003f8
X #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x00000404
+#define AOFF_task_ngroups	0x000003fc
X #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000408
+#define AOFF_task_groups	0x00000400
X #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000488
+#define AOFF_task_cap_effective	0x00000480
X #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000048c
+#define AOFF_task_cap_inheritable	0x00000484
X #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000490
+#define AOFF_task_cap_permitted	0x00000488
X #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000498
+#define AOFF_task_user	0x00000490
X #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x000004a0
+#define AOFF_task_rlim	0x00000498
X #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000540
+#define AOFF_task_used_math	0x00000538
X #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000542
+#define AOFF_task_comm	0x0000053a
X #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000554
+#define AOFF_task_link_count	0x0000054c
X #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000558
+#define AOFF_task_tty	0x00000550
X #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000560
+#define AOFF_task_semundo	0x00000558
X #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000568
+#define AOFF_task_semsleeping	0x00000560
X #define ASIZ_task_semsleeping	0x00000008
X #define AOFF_task_tss	0x00000570
-#define ASIZ_task_tss	0x00000470
-#define AOFF_task_fs	0x000009e0
+#define ASIZ_task_tss	0x00000460
+#define AOFF_task_fs	0x000009d0
X #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000009e8
+#define AOFF_task_files	0x000009d8
X #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000009f0
+#define AOFF_task_mm	0x000009e0
X #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000009f8
+#define AOFF_task_sigmask_lock	0x000009e8
X #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x00000a00
+#define AOFF_task_sig	0x000009f0
X #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x00000a08
+#define AOFF_task_signal	0x000009f8
X #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000a10
+#define AOFF_task_blocked	0x00000a00
X #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000a18
+#define AOFF_task_sigqueue	0x00000a08
X #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000a20
+#define AOFF_task_sigqueue_tail	0x00000a10
X #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000a28
+#define AOFF_task_sas_ss_sp	0x00000a18
X #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000a30
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 38'
echo 'File patch-2.3.4 is continued in part 39'
echo 39 > _shar_seq_.tmp
#!/bin/sh
# this is part 40 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 40; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+                              ISDN_TIMER_NETDIAL | ISDN_TIMER_KEEPALIVE | \
+                              ISDN_TIMER_CARRIER)
X 
X /* Timeout-Values for isdn_net_dial() */
X #define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
X #define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
X 
X /* GLOBAL_FLAGS */
X #define ISDN_GLOBAL_STOPPED 1
@@ -398,6 +514,7 @@
X #define ISDN_NET_TMP        0x10       /* tmp interface until getting an IP */
X #define ISDN_NET_DYNAMIC    0x20       /* this link is dynamically allocated */
X #endif
+
X #define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
X 
X /* Phone-list-element */
@@ -488,6 +605,11 @@
X 				    struct device *,
X                                     unsigned char *);
X   int  pppbind;                        /* ippp device for bindings         */
+  int					dialtimeout;	/* How long shall we try on dialing? (jiffies) */
+  int					dialwait;		/* How long shall we wait after failed attempt? (jiffies) */
+  ulong					dialstarted;	/* jiffies of first dialing-attempt */
+  ulong					dialwait_timer;	/* jiffies of earliest next dialing-attempt */
+  int					huptimeout;		/* How long will the connection be up? (seconds) */
X #ifdef CONFIG_ISDN_X25
X   struct concap_device_ops *dops;      /* callbacks used by encapsulator   */
X #endif
@@ -496,18 +618,6 @@
X   ulong cisco_yourseq;                 /* Remote keepalive seq. for Cisco  */
X } isdn_net_local;
X 
-#ifdef CONFIG_ISDN_PPP
-struct ippp_bundle {
-  int mp_mrru;                        /* unused                             */
-  struct mpqueue *last;               /* currently defined in isdn_net_dev  */
-  int min;                            /* currently calculated 'on the fly'  */
-  long next_num;                      /* we wanna see this seq.-number next */
-  struct sqqueue *sq;
-  int modify:1;                       /* set to 1 while modifying sqqueue   */
-  int bundled:1;                      /* bundle active ?                    */
-};
-#endif
-
X /* the interface itself */
X typedef struct isdn_net_dev_s {
X   isdn_net_local *local;
@@ -567,6 +677,10 @@
X 	u_char       mdmreg[ISDN_MODEM_ANZREG];  /* Modem-Registers                    */
X 	char         pmsn[ISDN_MSNLEN];          /* EAZ/MSNs Profile 0                 */
X 	char         msn[ISDN_MSNLEN];           /* EAZ/MSN                            */
+	char         plmsn[ISDN_LMSNLEN];        /* Listening MSNs Profile 0           */
+	char         lmsn[ISDN_LMSNLEN];         /* Listening MSNs                     */
+	char         cpn[ISDN_MSNLEN];           /* CalledPartyNumber on incoming call */
+	char         connmsg[ISDN_CMSGLEN];	 /* CONNECT-Msg from HL-Driver	       */
X #ifdef CONFIG_ISDN_AUDIO
X 	u_char       vpar[10];                   /* Voice-parameters                   */
X 	int          lastDLE;                    /* Flag for voice-coding: DLE seen    */
@@ -574,6 +688,7 @@
X 	int          mdmcmdl;                    /* Length of Modem-Commandbuffer      */
X 	int          pluscount;                  /* Counter for +++ sequence           */
X 	int          lastplus;                   /* Timestamp of last +                */
+	int	     carrierwait;                /* Seconds of carrier waiting         */
X 	char         mdmcmd[255];                /* Modem-Commandbuffer                */
X 	unsigned int charge;                     /* Charge units of current connection */
X } atemu;
@@ -593,7 +708,7 @@
X   long			pgrp;		 /* pgrp of opening process        */
X   int                   online;          /* 1 = B-Channel is up, drop data */
X 					 /* 2 = B-Channel is up, deliver d.*/
-  int                   dialing;         /* Dial in progress               */
+  int                   dialing;         /* Dial in progress or ATA        */
X   int                   rcvsched;        /* Receive needs schedule         */
X   int                   isdn_driver;	 /* Index to isdn-driver           */
X   int                   isdn_channel;    /* Index to isdn-channel          */
@@ -612,6 +727,7 @@
X   int                   xmit_count;      /* # of chars in xmit_buf         */
X   unsigned char         *xmit_buf;       /* transmit buffer                */
X   struct sk_buff_head   xmit_queue;      /* transmit queue                 */
+  atomic_t              xmit_lock;       /* Semaphore for isdn_tty_write   */
X #ifdef CONFIG_ISDN_AUDIO
X   int                   vonline;         /* Voice-channel status           */
X 					 /* Bit 0 = recording              */
@@ -621,12 +737,19 @@
X   void                  *adpcms;         /* state for adpcm decompression  */
X   void                  *adpcmr;         /* state for adpcm compression    */
X   void                  *dtmf_state;     /* state for dtmf decoder         */
+  void                  *silence_state;  /* state for silence detection    */
X #endif
X   struct tty_struct 	*tty;            /* Pointer to corresponding tty   */
X   atemu                 emu;             /* AT-emulator data               */
X   struct termios	normal_termios;  /* For saving termios structs     */
X   struct termios	callout_termios;
-  wait_queue_head_t 	open_wait, close_wait;
+#if LINUX_VERSION_CODE < 131841
+  struct wait_queue	*open_wait;
+  struct wait_queue	*close_wait;
+#else
+  wait_queue_head_t	open_wait, close_wait;
+#endif
+  struct semaphore      write_sem;
X } modem_info;
X 
X #define ISDN_MODEM_WINSIZE 8
@@ -644,72 +767,6 @@
X 
X /*======================= End of ISDN-tty stuff ============================*/
X 
-/*======================= Start of sync-ppp stuff ==========================*/
-
-
-#define NUM_RCV_BUFFS     64
-#define PPP_HARD_HDR_LEN 4
-
-#ifdef CONFIG_ISDN_PPP
-
-struct sqqueue {
-  struct sqqueue *next;
-  long sqno_start;
-  long sqno_end;
-  struct sk_buff *skb;
-  long timer;
-};
-  
-struct mpqueue {
-  struct mpqueue *next;
-  struct mpqueue *last;
-  long sqno;
-  struct sk_buff *skb;
-  int BEbyte;
-  unsigned long time;
-}; 
-
-struct ippp_buf_queue {
-  struct ippp_buf_queue *next;
-  struct ippp_buf_queue *last;
-  char *buf;                 /* NULL here indicates end of queue */
-  int len;
-};
-
-struct ippp_struct {
-  struct ippp_struct *next_link;
-  int state;
-  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
-  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
-  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
-  wait_queue_head_t wq;
-  wait_queue_head_t wql;
-  struct task_struct *tk;
-  unsigned int mpppcfg;
-  unsigned int pppcfg;
-  unsigned int mru;
-  unsigned int mpmru;
-  unsigned int mpmtu;
-  unsigned int maxcid;
-  isdn_net_local *lp;
-  int unit; 
-  int minor;
-  long last_link_seqno;
-  long mp_seqno;
-  long range;
-#ifdef CONFIG_ISDN_PPP_VJ
-  unsigned char *cbuf;
-  struct slcompress *slcomp;
-#endif
-  unsigned long debug;
-  struct isdn_ppp_compressor *compressor,*link_compressor;
-  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
-};
-
-#endif
-
-/*======================== End of sync-ppp stuff ===========================*/
-
X /*======================== Start of V.110 stuff ============================*/
X #define V110_BUFSIZE 1024
X 
@@ -742,69 +799,103 @@
X 	char *private;
X } infostruct;
X 
+typedef struct isdn_module {
+	struct isdn_module *prev;
+	struct isdn_module *next;
+	char *name;
+	int (*get_free_channel)(int, int, int, int, int);
+	int (*free_channel)(int, int, int);
+	int (*status_callback)(isdn_ctrl *);
+	int (*command)(isdn_ctrl *);
+	int (*receive_callback)(int, int, struct sk_buff *);
+	int (*writebuf_skb)(int, int, int, struct sk_buff *);
+	int (*net_start_xmit)(struct sk_buff *, struct device *);
+	int (*net_receive)(struct device *, struct sk_buff *);
+	int (*net_open)(struct device *);
+	int (*net_close)(struct device *);
+	int priority;
+} isdn_module;
+
+#define DRV_FLAG_RUNNING 1
+#define DRV_FLAG_REJBUS  2
+#define DRV_FLAG_LOADED  4
+
X /* Description of hardware-level-driver */
X typedef struct {
-  ulong               flags;            /* Flags                            */
-  int                 channels;         /* Number of channels               */
-  int                 reject_bus;       /* Flag: Reject rejected call on bus*/
-  wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
-  int                 maxbufsize;       /* Maximum Buffersize supported     */
-  unsigned long       pktcount;         /* Until now: unused                */
-  int                 running;          /* Flag: Protocolcode running       */
-  int                 loaded;           /* Flag: Driver loaded              */
-  int                 stavail;          /* Chars avail on Status-device     */
-  isdn_if            *interface;        /* Interface to driver              */
-  int                *rcverr;           /* Error-counters for B-Ch.-receive */
-  int                *rcvcount;         /* Byte-counters for B-Ch.-receive  */
+	ulong               online;           /* Channel-Online flags             */
+	ulong               flags;            /* Misc driver Flags                */
+	int                 locks;            /* Number of locks for this driver  */
+	int                 channels;         /* Number of channels               */
+#if LINUX_VERSION_CODE < 131841
+	struct wait_queue  *st_waitq;         /* Wait-Queue for status-read's     */
+#else
+	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
+#endif
+	int                 maxbufsize;       /* Maximum Buffersize supported     */
+	unsigned long       pktcount;         /* Until now: unused                */
+	int                 stavail;          /* Chars avail on Status-device     */
+	isdn_if            *interface;        /* Interface to driver              */
+	int                *rcverr;           /* Error-counters for B-Ch.-receive */
+	int                *rcvcount;         /* Byte-counters for B-Ch.-receive  */
X #ifdef CONFIG_ISDN_AUDIO
-  unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
+	unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
X #endif
-  struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
-  wait_queue_head_t  *rcv_waitq;  /* array of Wait-Queues for B-Channel-Reads  */
-  wait_queue_head_t  *snd_waitq;  /* array of Wait-Queue for B-Channel-Sends  */
-  char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
+	struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
+#if LINUX_VERSION_CODE < 131841
+	struct wait_queue  **rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
+	struct wait_queue  **snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
+#else
+	wait_queue_head_t  *rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
+	wait_queue_head_t  *snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
+#endif
+	char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
X } driver;
X 
X /* Main driver-data */
X typedef struct isdn_devt {
-  unsigned short    flags;		       /* Bitmapped Flags:           */
-				               /*                            */
-  int               drivers;		       /* Current number of drivers  */
-  int               channels;		       /* Current number of channels */
-  int               net_verbose;               /* Verbose-Flag               */
-  int               modempoll;		       /* Flag: tty-read active      */
-  int               tflags;                    /* Timer-Flags:               */
-				               /*  see ISDN_TIMER_..defines  */
-  int               global_flags;
-  infostruct        *infochain;                /* List of open info-devs.    */
-  wait_queue_head_t info_waitq;               /* Wait-Queue for isdninfo    */
-  struct timer_list timer;		       /* Misc.-function Timer       */
-  int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
-  int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
-  int               usage[ISDN_MAX_CHANNELS];  /* Used by tty/ip/voice       */
-  char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
-                                               /* Remote number of active ch.*/
-  int               m_idx[ISDN_MAX_CHANNELS];  /* Index for mdm....          */
-  driver            *drv[ISDN_MAX_DRIVERS];    /* Array of drivers           */
-  isdn_net_dev      *netdev;		       /* Linked list of net-if's    */
-  char              drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID                 */
-  struct task_struct *profd;                   /* For iprofd                 */
-  modem             mdm;		       /* tty-driver-data            */
-  isdn_net_dev      *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers     */
-  isdn_net_dev      *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers   */
-  ulong             ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes  */
-  ulong             obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes  */
-  int               v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
-  atomic_t          v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
-  isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
-  struct semaphore  sem;                       /* serialize list access*/
+	unsigned short    flags;		       /* Bitmapped Flags:           */
+	/*                            */
+	int               drivers;		       /* Current number of drivers  */
+	int               channels;		       /* Current number of channels */
+	int               net_verbose;               /* Verbose-Flag               */
+	int               modempoll;		       /* Flag: tty-read active      */
+	int               tflags;                    /* Timer-Flags:               */
+	/*  see ISDN_TIMER_..defines  */
+	int               global_flags;
+	infostruct        *infochain;                /* List of open info-devs.    */
+#if LINUX_VERSION_CODE < 131841
+	struct wait_queue *info_waitq;               /* Wait-Queue for isdninfo    */
+#else
+	wait_queue_head_t info_waitq;               /* Wait-Queue for isdninfo    */
+#endif
+	struct timer_list timer;		       /* Misc.-function Timer       */
+	int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
+	int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
+	int               usage[ISDN_MAX_CHANNELS];  /* Used by tty/ip/voice       */
+	char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
+	/* Remote number of active ch.*/
+	int               m_idx[ISDN_MAX_CHANNELS];  /* Index for mdm....          */
+	driver            *drv[ISDN_MAX_DRIVERS];    /* Array of drivers           */
+	isdn_net_dev      *netdev;		       /* Linked list of net-if's    */
+	char              drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID                 */
+	struct task_struct *profd;                   /* For iprofd                 */
+	modem             mdm;		       /* tty-driver-data            */
+	isdn_net_dev      *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers     */
+	isdn_net_dev      *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers   */
+	ulong             ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes  */
+	ulong             obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes  */
+	int               v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
+	atomic_t          v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
+	isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
+	struct semaphore  sem;                       /* serialize list access*/
+	isdn_module       *modules;
X } isdn_dev;
X 
X extern isdn_dev *dev;
X 
+
X /* Utility-Macros */
X #define MIN(a,b) ((a<b)?a:b)
X #define MAX(a,b) ((a>b)?a:b)
-
X #endif /* __KERNEL__ */
X #endif /* isdn_h */
diff -u --recursive --new-file v2.3.3/linux/include/linux/isdn_budget.h linux/include/linux/isdn_budget.h
--- v2.3.3/linux/include/linux/isdn_budget.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isdn_budget.h	Sun May 23 10:03:42 1999
@@ -0,0 +1,62 @@
+/* isdn_budget.h
+ *
+ * Linux ISDN subsystem, budget-accounting for network interfaces.
+ *
+ * Copyright 1997       by Christian Lademann <c...@zls.de>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+/*
+30.06.97:cal:angelegt
+04.11.97:cal:budget.period: int --> time_t
+*/
+
+#ifndef __isdn_budget_h__
+#define __isdn_budget_h__
+
+#include	<linux/types.h>
+
+#define	ISDN_BUDGET_DIAL		0
+#define	ISDN_BUDGET_CHARGE		1
+#define	ISDN_BUDGET_ONLINE		2
+#define	ISDN_BUDGET_NUM_BUDGET		3
+
+#define	ISDN_BUDGET_INIT		0
+#define	ISDN_BUDGET_CHECK_DIAL		1
+#define	ISDN_BUDGET_CHECK_CHARGE	2
+#define	ISDN_BUDGET_CHECK_ONLINE	3
+#define	ISDN_BUDGET_START_ONLINE	10
+
+#define	ISDN_BUDGET_SET_BUDGET	0
+#define	ISDN_BUDGET_GET_BUDGET	1
+
+typedef struct {
+	char	name [9];		/* Interface */
+	int	command,		/* subcommand */
+		budget,			/* budget-nr. */
+		amount,			/* set/get budget-amount */
+		used;			/* set/get used amount */
+	time_t	period,			/* set/get length of period */
+		period_started;		/* set/get startpoint of period */
+}	isdn_ioctl_budget;
+
+#ifdef __KERNEL__
+extern int	isdn_net_budget(int, struct device *);
+extern int	isdn_budget_ioctl(isdn_ioctl_budget *);
+#endif /* __KERNEL__ */
+
+#endif /* __isdn_budget_h__ */
diff -u --recursive --new-file v2.3.3/linux/include/linux/isdn_lzscomp.h linux/include/linux/isdn_lzscomp.h
--- v2.3.3/linux/include/linux/isdn_lzscomp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isdn_lzscomp.h	Sun May 23 10:03:42 1999
@@ -0,0 +1,26 @@
+/*
+ * $Id: isdn_lzscomp.h,v 1.1 1998/07/08 16:52:33 hipp Exp $
+ *
+ * Header for isdn_lzscomp.c
+ * Concentrated here to not mess up half a dozen kernel headers with code
+ * snippets
+ *
+ */
+
+#define CI_LZS_COMPRESS		17
+#define CILEN_LZS_COMPRESS	5
+
+#define LZS_CMODE_NONE		0
+#define LZS_CMODE_LCB		1
+#define LZS_CMODE_CRC		2
+#define LZS_CMODE_SEQNO		3	/* MUST be implemented (default) */
+#define LZS_CMODE_EXT		4	/* Seems to be what Win0.95 uses */
+
+#define LZS_COMP_MAX_HISTS	1	/* Don't waste peers ressources */
+#define LZS_COMP_DEF_HISTS	1	/* Most likely to negotiate */
+#define LZS_DECOMP_MAX_HISTS	32	/* More is really nonsense */
+#define LZS_DECOMP_DEF_HISTS	8	/* If we get it, this may be optimal */
+
+#define LZS_HIST_BYTE1(word)   	(word>>8)	/* Just for better reading */
+#define LZS_HIST_BYTE2(word)	(word&0xff)	/* of this big endian stuff */
+#define LZS_HIST_WORD(b1,b2)	((b1<<8)|b2)	/* (network byte order rulez) */
diff -u --recursive --new-file v2.3.3/linux/include/linux/isdn_ppp.h linux/include/linux/isdn_ppp.h
--- v2.3.3/linux/include/linux/isdn_ppp.h	Wed Apr  1 16:20:56 1998
+++ linux/include/linux/isdn_ppp.h	Wed May 26 16:55:40 1999
@@ -1,19 +1,22 @@
+/* -*- mode: c; c-basic-offset: 2 -*- */
+
X #ifndef _LINUX_ISDN_PPP_H
X #define _LINUX_ISDN_PPP_H
X 
-extern int isdn_ppp_dial_slave(char *);
-extern int isdn_ppp_hangup_slave(char *);
+#include <linux/config.h>
X 
X #define CALLTYPE_INCOMING 0x1
X #define CALLTYPE_OUTGOING 0x2
X #define CALLTYPE_CALLBACK 0x4
X 
+#define IPPP_VERSION    "2.2.0"
+
X struct pppcallinfo
X {
-	int calltype;
-	unsigned char local_num[64];
-	unsigned char remote_num[64];
-	int charge_units;
+  int calltype;
+  unsigned char local_num[64];
+  unsigned char remote_num[64];
+  int charge_units;
X };
X 
X #define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo)
@@ -22,48 +25,216 @@
X #define PPPIOCSMPFLAGS _IOW('t',131,int)
X #define PPPIOCSMPMTU   _IOW('t',132,int)
X #define PPPIOCSMPMRU   _IOW('t',133,int)
-#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long)
+#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8])
X #define PPPIOCSCOMPRESSOR _IOW('t',135,int)
+#define PPPIOCGIFNAME      _IOR('t',136, char [IFNAMSIZ] )
X 
X #define PPP_MP          0x003d
X #define PPP_LINK_COMP   0x00fb
+#define PPP_LINK_CCP    0x80fb
X 
X #define SC_MP_PROT       0x00000200
X #define SC_REJ_MP_PROT   0x00000400
X #define SC_OUT_SHORT_SEQ 0x00000800
X #define SC_IN_SHORT_SEQ  0x00004000
X 
+#define SC_DECOMP_ON		0x01
+#define SC_COMP_ON		0x02
+#define SC_DECOMP_DISCARD	0x04
+#define SC_COMP_DISCARD		0x08
+#define SC_LINK_DECOMP_ON	0x10
+#define SC_LINK_COMP_ON		0x20
+#define SC_LINK_DECOMP_DISCARD	0x40
+#define SC_LINK_COMP_DISCARD	0x80
+
+#define DECOMP_ERR_NOMEM	(-10)
+
X #define MP_END_FRAG    0x40
X #define MP_BEGIN_FRAG  0x80
X 
+#define ISDN_PPP_COMP_MAX_OPTIONS 16
+
+#define IPPP_COMP_FLAG_XMIT 0x1
+#define IPPP_COMP_FLAG_LINK 0x2
+
+struct isdn_ppp_comp_data {
+  int num;
+  unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
+  int optlen;
+  int flags;
+};
+
X #ifdef __KERNEL__
+
+/*
+ * We need a way for the decompressor to influence the generation of CCP
+ * Reset-Requests in a variety of ways. The decompressor is already returning
+ * a lot of information (generated skb length, error conditions) so we use
+ * another parameter. This parameter is a pointer to a structure which is
+ * to be marked valid by the decompressor and only in this case is ever used.
+ * Furthermore, the only case where this data is used is when the decom-
+ * pressor returns DECOMP_ERROR.
+ *
+ * We use this same struct for the reset entry of the compressor to commu-
+ * nicate to its caller how to deal with sending of a Reset Ack. In this
+ * case, expra is not used, but other options still apply (supressing
+ * sending with rsend, appending arbitrary data, etc).
+ */
+
+#define IPPP_RESET_MAXDATABYTES	32
+
+struct isdn_ppp_resetparams {
+  unsigned char valid:1;	/* rw Is this structure filled at all ? */
+  unsigned char rsend:1;	/* rw Should we send one at all ? */
+  unsigned char idval:1;	/* rw Is the id field valid ? */
+  unsigned char dtval:1;	/* rw Is the data field valid ? */
+  unsigned char expra:1;	/* rw Is an Ack expected for this Req ? */
+  unsigned char id;		/* wo Send CCP ResetReq with this id */
+  unsigned short maxdlen;	/* ro Max bytes to be stored in data field */
+  unsigned short dlen;		/* rw Bytes stored in data field */
+  unsigned char *data;		/* wo Data for ResetReq info field */
+};
+
X /*
X  * this is an 'old friend' from ppp-comp.h under a new name 
X  * check the original include for more information
X  */
X struct isdn_ppp_compressor {
-	struct isdn_ppp_compressor *next,*prev;
-	int num; /* CCP compression protocol number */
-	void *(*comp_alloc) (unsigned char *options, int opt_len);
-	void (*comp_free) (void *state);
-	int  (*comp_init) (void *state, unsigned char *options, int opt_len,
-		 int unit, int opthdr, int debug);
-	void (*comp_reset) (void *state);
-	int  (*compress) (void *state,struct sk_buff *in, struct sk_buff *skb_out,
-		 int proto);
-	void (*comp_stat) (void *state, struct compstat *stats);
-	void *(*decomp_alloc) (unsigned char *options, int opt_len);
-	void (*decomp_free) (void *state);
-	int  (*decomp_init) (void *state, unsigned char *options,
-			int opt_len, int unit, int opthdr, int mru, int debug);
-	void (*decomp_reset) (void *state);
-	int  (*decompress) (void *state, unsigned char *ibuf, int isize, unsigned char *obuf, int osize);
-	void (*incomp) (void *state, unsigned char *ibuf, int icnt);
-	void (*decomp_stat) (void *state, struct compstat *stats);
+  struct isdn_ppp_compressor *next, *prev;
+  int num; /* CCP compression protocol number */
+  
+  void *(*alloc) (struct isdn_ppp_comp_data *);
+  void (*free) (void *state);
+  int  (*init) (void *state, struct isdn_ppp_comp_data *,
+		int unit,int debug);
+  
+  /* The reset entry needs to get more exact information about the
+     ResetReq or ResetAck it was called with. The parameters are
+     obvious. If reset is called without a Req or Ack frame which
+     could be handed into it, code MUST be set to 0. Using rsparm,
+     the reset entry can control if and how a ResetAck is returned. */
+  
+  void (*reset) (void *state, unsigned char code, unsigned char id,
+		 unsigned char *data, unsigned len,
+		 struct isdn_ppp_resetparams *rsparm);
+  
+  int  (*compress) (void *state, struct sk_buff *in,
+		    struct sk_buff *skb_out, int proto);
+  
+	int  (*decompress) (void *state,struct sk_buff *in,
+			    struct sk_buff *skb_out,
+			    struct isdn_ppp_resetparams *rsparm);
+  
+  void (*incomp) (void *state, struct sk_buff *in,int proto);
+  void (*stat) (void *state, struct compstat *stats);
X };
X 
X extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *);
X extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
+extern int isdn_ppp_dial_slave(char *);
+extern int isdn_ppp_hangup_slave(char *);
+
+struct ippp_bundle {
+  int mp_mrru;                        /* unused                             */
+  struct mpqueue *last;               /* currently defined in isdn_net_dev  */
+  int min;                            /* currently calculated 'on the fly'  */
+  long next_num;                      /* we wanna see this seq.-number next */
+  struct sqqueue *sq;
+  int modify:1;                       /* set to 1 while modifying sqqueue   */
+  int bundled:1;                      /* bundle active ?                    */
+};
+
+#define NUM_RCV_BUFFS     64
+
+struct sqqueue {
+  struct sqqueue *next;
+  long sqno_start;
+  long sqno_end;
+  struct sk_buff *skb;
+  long timer;
+};
+
+struct mpqueue {
+  struct mpqueue *next;
+  struct mpqueue *last;
+  long sqno;
+  struct sk_buff *skb;
+  int BEbyte;
+  unsigned long time;
+};
+
+struct ippp_buf_queue {
+  struct ippp_buf_queue *next;
+  struct ippp_buf_queue *last;
+  char *buf;                 /* NULL here indicates end of queue */
+  int len;
+};
+
+/* The data structure for one CCP reset transaction */
+enum ippp_ccp_reset_states {
+  CCPResetIdle,
+  CCPResetSentReq,
+  CCPResetRcvdReq,
+  CCPResetSentAck,
+  CCPResetRcvdAck
+};
+
+struct ippp_ccp_reset_state {
+  enum ippp_ccp_reset_states state;	/* State of this transaction */
+  struct ippp_struct *is;		/* Backlink to device stuff */
+  unsigned char id;			/* Backlink id index */
+  unsigned char ta:1;			/* The timer is active (flag) */
+  unsigned char expra:1;		/* We expect a ResetAck at all */
+  int dlen;				/* Databytes stored in data */
+  struct timer_list timer;		/* For timeouts/retries */
+  /* This is a hack but seems sufficient for the moment. We do not want
+     to have this be yet another allocation for some bytes, it is more
+     memory management overhead than the whole mess is worth. */
+  unsigned char data[IPPP_RESET_MAXDATABYTES];
+};
+
+/* The data structure keeping track of the currently outstanding CCP Reset
+   transactions. */
+struct ippp_ccp_reset {
+  struct ippp_ccp_reset_state *rs[256];	/* One per possible id */
+  unsigned char lastid;			/* Last id allocated by the engine */
+};
+
+struct ippp_struct {
+  struct ippp_struct *next_link;
+  int state;
+  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
+  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
+  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
+#if LINUX_VERSION_CODE < 131841
+  struct wait_queue *wq;
+#else
+  wait_queue_head_t wq;
+#endif
+  struct task_struct *tk;
+  unsigned int mpppcfg;
+  unsigned int pppcfg;
+  unsigned int mru;
+  unsigned int mpmru;
+  unsigned int mpmtu;
+  unsigned int maxcid;
+  struct isdn_net_local_s *lp;
+  int unit;
+  int minor;
+  long last_link_seqno;
+  long mp_seqno;
+  long range;
+#ifdef CONFIG_ISDN_PPP_VJ
+  unsigned char *cbuf;
+  struct slcompress *slcomp;
+#endif
+  unsigned long debug;
+  struct isdn_ppp_compressor *compressor,*decompressor;
+  struct isdn_ppp_compressor *link_compressor,*link_decompressor;
+  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
+  struct ippp_ccp_reset *reset;	/* Allocated on demand, may never be needed */
+  unsigned long compflags;
+};
X 
X #endif /* __KERNEL__ */
X 
diff -u --recursive --new-file v2.3.3/linux/include/linux/isdn_timru.h linux/include/linux/isdn_timru.h
--- v2.3.3/linux/include/linux/isdn_timru.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isdn_timru.h	Sun May 23 10:03:42 1999
@@ -0,0 +1,119 @@
+/* isdn_timru.h
+ *
+ * Linux ISDN subsystem, timeout-rules for network interfaces.
+ *
+ * Copyright 1997       by Christian Lademann <c...@zls.de>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+/*
+02.06.97:cal:ISDN_TIMRU_PACKET_NONE def., ISDN_TIMRU_PACKET_* inkr.
+*/
+
+#ifndef __isdn_timru_h__
+#define __isdn_timru_h__
+
+#define	ISDN_TIMRU_PACKET_NONE		0
+#define	ISDN_TIMRU_PACKET_SKB		1
+#define	ISDN_TIMRU_PACKET_PPP		2
+#define	ISDN_TIMRU_PACKET_PPP_NO_HEADER	3
+
+#define	ISDN_TIMRU_BRINGUP		0
+#define	ISDN_TIMRU_KEEPUP_IN		1
+#define	ISDN_TIMRU_KEEPUP_OUT		2
+#define	ISDN_TIMRU_BRINGDOWN		3
+#define	ISDN_TIMRU_NUM_CHECK		4
+
+#define	ISDN_TIMRU_PROTFAM_WILDCARD	0
+#define	ISDN_TIMRU_PROTFAM_IP		1
+#define	ISDN_TIMRU_PROTFAM_PPP		2
+#define	ISDN_TIMRU_PROTFAM_IPX		3
+#define	ISDN_TIMRU_NUM_PROTFAM		4
+
+#define	ISDN_TIMRU_IP_WILDCARD		0
+#define	ISDN_TIMRU_IP_ICMP		1
+#define	ISDN_TIMRU_IP_TCP		2
+#define	ISDN_TIMRU_IP_UDP		3
+
+#define	ISDN_TIMRU_PPP_WILDCARD		0
+#define	ISDN_TIMRU_PPP_IPCP		1
+#define	ISDN_TIMRU_PPP_IPXCP		2
+#define	ISDN_TIMRU_PPP_CCP		3
+#define	ISDN_TIMRU_PPP_LCP		4
+#define	ISDN_TIMRU_PPP_PAP		5
+#define	ISDN_TIMRU_PPP_LQR		6
+#define	ISDN_TIMRU_PPP_CHAP		7
+
+typedef struct {
+	struct in_addr	saddr,		/* Source Address */
+			smask,		/* Source Subnetmask */
+			daddr,		/* Dest. Address */
+			dmask;		/* Dest. Subnetmask */
+	ushort		protocol;	/* TCP, UDP, ... */
+	union {
+		struct {
+			__u16	s_from,	/* Source Port */
+				s_to,
+				d_from,
+				d_to;
+		}		port;
+		struct {
+			__u8	from,	/* ICMP-Type */
+				to;
+		}		type;
+	}		pt;
+}	isdn_timeout_rule_ip;
+
+
+typedef struct {
+	ushort		protocol;	/* IPCP, LCP, ... */
+}	isdn_timeout_rule_ppp;
+
+
+typedef struct isdn_timeout_rule_s {
+	struct isdn_timeout_rule_s	*next,		/* Pointer to next rule */
+					*prev;		/* Pointer to previous rule */
+	ushort				type,		/* BRINGUP, KEEPUP_*, ... */
+					neg;
+	int				timeout;	/* Timeout value */
+	ushort				protfam;	/* IP, IPX, PPP, ... */
+	union {
+		isdn_timeout_rule_ip	ip;	/* IP-Rule */
+		isdn_timeout_rule_ppp	ppp;	/* PPP-Rule */
+	}				rule;	/* Prot.-specific rule */
+}	isdn_timeout_rule;
+
+
+typedef struct {
+	char			name [9];	/* Interface */
+	int			where,		/* 0/1: add to start/end of list, -1: handle default */
+				type,
+				protfam,
+				index,
+				defval;
+	isdn_timeout_rule	rule;		/* Rule */
+}	isdn_ioctl_timeout_rule;
+
+#ifdef __KERNEL__
+extern int	isdn_net_recalc_timeout(int, int, struct device *, void *, ulong);
+extern int	isdn_timru_alloc_timeout_rules(struct device *);
+extern int	isdn_timru_ioctl_add_rule(isdn_ioctl_timeout_rule *);
+extern int	isdn_timru_ioctl_del_rule(isdn_ioctl_timeout_rule *);
+extern int	isdn_timru_ioctl_get_rule(isdn_ioctl_timeout_rule *);
+#endif /* __KERNEL__ */
+
+#endif /* __isdn_timru_h__ */
diff -u --recursive --new-file v2.3.3/linux/include/linux/isdnif.h linux/include/linux/isdnif.h
--- v2.3.3/linux/include/linux/isdnif.h	Wed Apr  1 16:20:56 1998
+++ linux/include/linux/isdnif.h	Sun May 23 10:03:42 1999
@@ -1,8 +1,4 @@
-/* X25 changes:
-   Added constants ISDN_PROTO_L2_X25DTE/DCE and corresponding ISDN_FEATURE_..
-   */
-
-/* $Id: isdnif.h,v 1.23 1998/02/20 17:36:52 fritz Exp $
+/* $Id: isdnif.h,v 1.25 1998/06/17 19:51:55 he Exp $
X  *
X  * Linux ISDN subsystem
X  *
@@ -26,6 +22,15 @@
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
X  * $Log: isdnif.h,v $
+ * Revision 1.25  1998/06/17 19:51:55  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.24  1998/03/19 13:18:57  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
X  * Revision 1.23  1998/02/20 17:36:52  fritz
X  * Added L2-protocols for V.110, changed FEATURE-Flag-constants.
X  *
@@ -139,6 +144,7 @@
X #define ISDN_PROTO_L2_V11096 7   /* V.110 bitrate adaption 9600 Baud  */
X #define ISDN_PROTO_L2_V11019 8   /* V.110 bitrate adaption 19200 Baud */
X #define ISDN_PROTO_L2_V11038 9   /* V.110 bitrate adaption 38400 Baud */
+#define ISDN_PROTO_L2_MODEM  10  /* Analog Modem on Board */
X #define ISDN_PROTO_L2_MAX    15  /* Max. 16 Protocols                 */
X 
X /*
@@ -173,6 +179,7 @@
X #define ISDN_CMD_UNLOCK  15       /* Release usage-lock                    */
X #define ISDN_CMD_SUSPEND 16       /* Suspend connection                    */
X #define ISDN_CMD_RESUME  17       /* Resume connection                     */
+#define CAPI_PUT_MESSAGE 18       /* CAPI message send down or up          */
X 
X /*
X  * Status-Values delivered from lowlevel to linklevel via
@@ -216,6 +223,7 @@
X #define ISDN_FEATURE_L2_V11096  (0x0001 << ISDN_PROTO_L2_V11096)
X #define ISDN_FEATURE_L2_V11019  (0x0001 << ISDN_PROTO_L2_V11019)
X #define ISDN_FEATURE_L2_V11038  (0x0001 << ISDN_PROTO_L2_V11038)
+#define ISDN_FEATURE_L2_MODEM   (0x0001 << ISDN_PROTO_L2_MODEM)
X 
X #define ISDN_FEATURE_L2_MASK    (0x0FFFF) /* Max. 16 protocols */
X #define ISDN_FEATURE_L2_SHIFT   (0)
@@ -236,14 +244,37 @@
X #define ISDN_FEATURE_P_SHIFT    (24)
X 
X typedef struct setup_parm {
-    char phone[32];         /* Remote Phone-Number */
-    char eazmsn[32];        /* Local EAZ or MSN    */
+    unsigned char phone[32];	/* Remote Phone-Number */
+    unsigned char eazmsn[32];	/* Local EAZ or MSN    */
X     unsigned char si1;      /* Service Indicator 1 */
X     unsigned char si2;      /* Service Indicator 2 */
X     unsigned char plan;     /* Numbering plan      */
X     unsigned char screen;   /* Screening info      */
X } setup_parm;
X 
+/* CAPI structs */
+
+/* this is compatible to the old union size */
+#define MAX_CAPI_PARA_LEN 50
+
+typedef struct {
+	/* Header */
+	__u16 Length;
+	__u16 ApplId;
+	__u8 Command;
+	__u8 Subcommand;
+	__u16 Messagenumber;
+
+	/* Parameter */
+	union {
+		__u32 Controller;
+		__u32 PLCI;
+		__u32 NCCI;
+	} adr;
+	__u8 para[MAX_CAPI_PARA_LEN];
+} capi_msg;
+
+
X /*
X  * Structure for exchanging above infos
X  *
@@ -255,8 +286,9 @@
X   union {
X 	ulong errcode;               /* Type of error with STAT_L1ERR         */
X 	int   length;                /* Amount of bytes sent with STAT_BSENT  */
-	char  num[50];               /* Additional Data                       */
-	setup_parm setup;
+	u_char	num[50];	/* Additional Data			*/
+	setup_parm 	setup;	/* For SETUP msg			*/
+	capi_msg  	cmsg;	/* For CAPI like messages		*/
X   } parm;
X } isdn_ctrl;
X 
diff -u --recursive --new-file v2.3.3/linux/include/linux/lp.h linux/include/linux/lp.h
--- v2.3.3/linux/include/linux/lp.h	Fri May 14 18:55:29 1999
+++ linux/include/linux/lp.h	Sat May 22 12:42:27 1999
@@ -7,12 +7,6 @@
X  * Interrupt support added 1993 Nigel Gamble
X  */
X 
-/* Magic numbers for defining port-device mappings */
-#define LP_PARPORT_UNSPEC -4
-#define LP_PARPORT_AUTO -3
-#define LP_PARPORT_OFF -2
-#define LP_PARPORT_NONE -1
-
X /*
X  * Per POSIX guidelines, this module reserves the LP and lp prefixes
X  * These are the lp_table[minor].flags flags...
@@ -87,6 +81,14 @@
X #define LP_TIMEOUT_INTERRUPT	(60 * HZ)
X #define LP_TIMEOUT_POLLED	(10 * HZ)
X 
+#ifdef __KERNEL__
+
+/* Magic numbers for defining port-device mappings */
+#define LP_PARPORT_UNSPEC -4
+#define LP_PARPORT_AUTO -3
+#define LP_PARPORT_OFF -2
+#define LP_PARPORT_NONE -1
+
X #define LP_F(minor)	lp_table[(minor)].flags		/* flags for busy, etc. */
X #define LP_CHAR(minor)	lp_table[(minor)].chars		/* busy timeout */
X #define LP_TIME(minor)	lp_table[(minor)].time		/* wait time */
@@ -180,5 +182,7 @@
X  */
X 
X extern int lp_init(void);
+
+#endif
X 
X #endif
diff -u --recursive --new-file v2.3.3/linux/include/linux/major.h linux/include/linux/major.h
--- v2.3.3/linux/include/linux/major.h	Sat May 15 23:46:05 1999
+++ linux/include/linux/major.h	Mon May 31 22:08:10 1999
@@ -98,6 +98,8 @@
X #define IDE6_MAJOR	88
X #define IDE7_MAJOR	89
X 
+#define AURORA_MAJOR 79
+
X #define UNIX98_PTY_MASTER_MAJOR	128
X #define UNIX98_PTY_MAJOR_COUNT	8
X #define UNIX98_PTY_SLAVE_MAJOR	(UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
diff -u --recursive --new-file v2.3.3/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.3/linux/include/linux/netdevice.h	Mon May 17 09:55:23 1999
+++ linux/include/linux/netdevice.h	Wed May 26 18:14:37 1999
@@ -266,6 +266,9 @@
X 	struct Qdisc		*qdisc_list;
X 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
X 
+	/* hard_start_xmit synchronizer */
+	spinlock_t		xmit_lock;
+
X 	/* Pointers to interface service routines.	*/
X 	int			(*open)(struct device *dev);
X 	int			(*stop)(struct device *dev);
@@ -331,7 +334,7 @@
X 
X extern struct device		loopback_dev;		/* The loopback */
X extern struct device		*dev_base;		/* All devices */
-extern struct packet_type 	*ptype_base[16];	/* Hashed types */
+extern rwlock_t			dev_base_lock;		/* Device list lock */
X extern int			netdev_dropping;
X extern int			net_cpu_congestion;
X 
diff -u --recursive --new-file v2.3.3/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.3.3/linux/include/linux/pagemap.h	Tue May 11 13:04:23 1999
+++ linux/include/linux/pagemap.h	Tue May 25 14:58:57 1999
@@ -14,7 +14,7 @@
X 
X static inline unsigned long page_address(struct page * page)
X {
-	return PAGE_OFFSET + PAGE_SIZE * (page - mem_map);
+	return PAGE_OFFSET + ((page - mem_map) << PAGE_SHIFT);
X }
X 
X /*
diff -u --recursive --new-file v2.3.3/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.3.3/linux/include/linux/parport.h	Mon May 17 09:55:23 1999
+++ linux/include/linux/parport.h	Tue May 25 14:57:59 1999
@@ -212,6 +212,13 @@
X 	rwlock_t cad_lock;
X };
X 
+struct parport_driver {
+	const char *name;
+	void (*attach) (struct parport *);
+	void (*detach) (struct parport *);
+	struct parport_driver *next;
+};
+
X /* parport_register_port registers a new parallel port at the given address (if
X  * one does not already exist) and returns a pointer to it.  This entails
X  * claiming the I/O region, IRQ and DMA.
@@ -220,6 +227,13 @@
X struct parport *parport_register_port(unsigned long base, int irq, int dma,
X 				      struct parport_operations *ops);
X 
+/* Once a registered port is ready for high-level drivers to use, the
+   low-level driver that registered it should announce it.  This will
+   call the high-level drivers' attach() functions (after things like
+   determining the IEEE 1284.3 topology of the port and collecting
+   DeviceIDs). */
+void parport_announce_port (struct parport *port);
+
X /* Unregister a port. */
X extern void parport_unregister_port(struct parport *port);
X 
@@ -235,6 +249,12 @@
X  */
X struct parport *parport_enumerate(void);
X 
+/* Register a new high-level driver. */
+extern int parport_register_driver (struct parport_driver *);
+
+/* Unregister a high-level driver. */
+extern void parport_unregister_driver (struct parport_driver *);
+
X /* parport_register_device declares that a device is connected to a port, and 
X  * tells the kernel all it needs to know.  
X  * pf is the preemption function (may be NULL for no callback)
@@ -322,7 +342,8 @@
X #define PARPORT_FLAG_COMA		(1<<0)
X #define PARPORT_FLAG_EXCL		(1<<1)	/* EXCL driver registered. */
X 
-extern void parport_parse_irqs(int, const char *[], int irqval[]);
+extern int parport_parse_irqs(int, const char *[], int irqval[]);
+extern int parport_parse_dmas(int, const char *[], int irqval[]);
X extern int parport_ieee1284_nibble_mode_ok(struct parport *, unsigned char);
X extern int parport_wait_peripheral(struct parport *, unsigned char, unsigned
X 				   char);
diff -u --recursive --new-file v2.3.3/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.3/linux/include/linux/proc_fs.h	Sat May 15 23:46:05 1999
+++ linux/include/linux/proc_fs.h	Wed May 26 09:35:29 1999
@@ -135,11 +135,11 @@
X 	PROC_NET_TR_RIF,
X 	PROC_NET_DN_DEV,
X 	PROC_NET_DN_ADJ,
-	PROC_NET_DN_L1,
-	PROC_NET_DN_L2,
+	PROC_NET_DN_ROUTE,
X 	PROC_NET_DN_CACHE,
X 	PROC_NET_DN_SKT,
-	PROC_NET_DN_FW,
+	PROC_NET_DN_FW_CHAINS,
+	PROC_NET_DN_FW_CHAIN_NAMES,
X 	PROC_NET_DN_RAW,
X 	PROC_NET_NETSTAT,
X 	PROC_NET_IPFW_CHAINS,
diff -u --recursive --new-file v2.3.3/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
--- v2.3.3/linux/include/linux/rtnetlink.h	Fri May 14 18:55:30 1999
+++ linux/include/linux/rtnetlink.h	Wed May 26 09:36:35 1999
@@ -418,7 +418,9 @@
X 	IFLA_MTU,
X 	IFLA_LINK,
X 	IFLA_QDISC,
-	IFLA_STATS
+	IFLA_STATS,
+	IFLA_COST,
+	IFLA_PRIORITY
X };
X 
X 
@@ -505,6 +507,9 @@
X #define RTMGRP_IPV6_IFADDR	0x100
X #define RTMGRP_IPV6_MROUTE	0x200
X #define RTMGRP_IPV6_ROUTE	0x400
+
+#define RTMGRP_DECnet_IFADDR    0x1000
+#define RTMGRP_DECnet_ROUTE     0x4000
X 
X /* End of information exported to user level */
X 
diff -u --recursive --new-file v2.3.3/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.3/linux/include/linux/sched.h	Fri May 14 18:55:30 1999
+++ linux/include/linux/sched.h	Tue May 25 14:58:57 1999
@@ -16,6 +16,7 @@
X #include <asm/system.h>
X #include <asm/semaphore.h>
X #include <asm/page.h>
+#include <asm/ptrace.h>
X 
X #include <linux/smp.h>
X #include <linux/tty.h>
@@ -381,9 +382,13 @@
X /* signals */	SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
X }
X 
+#ifndef INIT_TASK_SIZE
+# define INIT_TASK_SIZE	2048*sizeof(long)
+#endif
+
X union task_union {
X 	struct task_struct task;
-	unsigned long stack[2048];
+	unsigned long stack[INIT_TASK_SIZE/sizeof(long)];
X };
X 
X extern union task_union init_task_union;
@@ -538,8 +543,7 @@
X 
X static inline int on_sig_stack(unsigned long sp)
X {
-	return (sp >= current->sas_ss_sp
-		&& sp < current->sas_ss_sp + current->sas_ss_size);
+	return (sp - current->sas_ss_sp < current->sas_ss_size);
X }
X 
X static inline int sas_ss_flags(unsigned long sp)
diff -u --recursive --new-file v2.3.3/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.3.3/linux/include/linux/skbuff.h	Fri May 14 18:55:30 1999
+++ linux/include/linux/skbuff.h	Mon May 31 22:07:43 1999
@@ -15,6 +15,8 @@
X #define _LINUX_SKBUFF_H
X 
X #include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
X #include <linux/time.h>
X 
X #include <asm/atomic.h>
@@ -30,15 +32,19 @@
X #define CHECKSUM_UNNECESSARY 2
X 
X struct sk_buff_head {
+	/* These two members must be first. */
X 	struct sk_buff	* next;
X 	struct sk_buff	* prev;
-	__u32		qlen;		/* Must be same length as a pointer
-					   for using debugging */
+
+	__u32		qlen;
+	spinlock_t	lock;
X };
X 
X struct sk_buff {
+	/* These two members must be first. */
X 	struct sk_buff	* next;			/* Next buffer in list 				*/
X 	struct sk_buff	* prev;			/* Previous buffer in list 			*/
+
X 	struct sk_buff_head * list;		/* List we are on				*/
X 	struct sock	*sk;			/* Socket we are owned by 			*/
X 	struct timeval	stamp;			/* Time we arrived				*/
@@ -245,6 +251,7 @@
X 
X extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
X {
+	spin_lock_init(&list->lock);
X 	list->prev = (struct sk_buff *)list;
X 	list->next = (struct sk_buff *)list;
X 	list->qlen = 0;
@@ -271,15 +278,13 @@
X 	prev->next = newsk;
X }
X 
-extern spinlock_t skb_queue_lock;
-
X extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
X {
X 	unsigned long flags;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
+	spin_lock_irqsave(&list->lock, flags);
X 	__skb_queue_head(list, newsk);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	spin_unlock_irqrestore(&list->lock, flags);
X }
X 
X /*
@@ -304,9 +309,9 @@
X {
X 	unsigned long flags;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
+	spin_lock_irqsave(&list->lock, flags);
X 	__skb_queue_tail(list, newsk);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	spin_unlock_irqrestore(&list->lock, flags);
X }
X 
X /*
@@ -338,9 +343,9 @@
X 	long flags;
X 	struct sk_buff *result;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
+	spin_lock_irqsave(&list->lock, flags);
X 	result = __skb_dequeue(list);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	spin_unlock_irqrestore(&list->lock, flags);
X 	return result;
X }
X 
@@ -367,9 +372,9 @@
X {
X 	unsigned long flags;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
+	spin_lock_irqsave(&old->list->lock, flags);
X 	__skb_insert(newsk, old->prev, old, old->list);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	spin_unlock_irqrestore(&old->list->lock, flags);
X }
X 
X /*
@@ -385,9 +390,9 @@
X {
X 	unsigned long flags;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
+	spin_lock_irqsave(&old->list->lock, flags);
X 	__skb_append(old, newsk);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	spin_unlock_irqrestore(&old->list->lock, flags);
X }
X 
X /*
@@ -417,12 +422,16 @@
X 
X extern __inline__ void skb_unlink(struct sk_buff *skb)
X {
-	unsigned long flags;
+	struct sk_buff_head *list = skb->list;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
-	if(skb->list)
-		__skb_unlink(skb, skb->list);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	if(list) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&list->lock, flags);
+		if(skb->list == list)
+			__skb_unlink(skb, skb->list);
+		spin_unlock_irqrestore(&list->lock, flags);
+	}
X }
X 
X /* XXX: more streamlined implementation */
@@ -439,9 +448,9 @@
X 	long flags;
X 	struct sk_buff *result;
X 
-	spin_lock_irqsave(&skb_queue_lock, flags);
+	spin_lock_irqsave(&list->lock, flags);
X 	result = __skb_dequeue_tail(list);
-	spin_unlock_irqrestore(&skb_queue_lock, flags);
+	spin_unlock_irqrestore(&list->lock, flags);
X 	return result;
X }
X 
@@ -462,11 +471,8 @@
X 	unsigned char *tmp=skb->tail;
X 	skb->tail+=len;
X 	skb->len+=len;
-	if(skb->tail>skb->end)
-	{
-		__label__ here; 
-		skb_over_panic(skb, len, &&here); 
-here:		;
+	if(skb->tail>skb->end) {
+		skb_over_panic(skb, len, current_text_addr());
X 	}
X 	return tmp;
X }
@@ -482,11 +488,8 @@
X {
X 	skb->data-=len;
X 	skb->len+=len;
-	if(skb->data<skb->head)
-	{
-		__label__ here;
-		skb_under_panic(skb, len, &&here);
-here: 		;
+	if(skb->data<skb->head) {
+		skb_under_panic(skb, len, current_text_addr());
X 	}
X 	return skb->data;
X }
diff -u --recursive --new-file v2.3.3/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.3/linux/include/linux/sysctl.h	Sat Apr 24 12:47:47 1999
+++ linux/include/linux/sysctl.h	Wed May 26 09:36:35 1999
@@ -392,14 +392,42 @@
X 	NET_TR_RIF_TIMEOUT=1
X };
X 
-/* /proc/sys/net/decnet */
+/* /proc/sys/net/decnet/ */
X enum {
-	NET_DECNET_DEF_T3_BROADCAST=1,
-	NET_DECNET_DEF_T3_POINTTOPOINT=2,
-	NET_DECNET_DEF_T1=3,
-	NET_DECNET_DEF_BCT1=4,
-	NET_DECNET_CACHETIMEOUT=5,
-	NET_DECNET_DEBUG_LEVEL=6
+	NET_DECNET_NODE_TYPE = 1,
+	NET_DECNET_NODE_ADDRESS = 2,
+	NET_DECNET_NODE_NAME = 3,
+	NET_DECNET_DEFAULT_DEVICE = 4,
+	NET_DECNET_TIME_WAIT = 5,
+	NET_DECNET_DN_COUNT = 6,
+	NET_DECNET_DI_COUNT = 7,
+	NET_DECNET_DR_COUNT = 8,
+	NET_DECNET_DST_GC_INTERVAL = 9,
+	NET_DECNET_CONF = 10,
+	NET_DECNET_DEBUG_LEVEL = 255
+};
+
+/* /proc/sys/net/decnet/conf/<dev> */
+enum {
+	NET_DECNET_CONF_LOOPBACK = -2,
+	NET_DECNET_CONF_DDCMP = -3,
+	NET_DECNET_CONF_PPP = -4,
+	NET_DECNET_CONF_X25 = -5,
+	NET_DECNET_CONF_GRE = -6,
+	NET_DECNET_CONF_ETHER = -7
+
+	/* ... and ifindex of devices */
+};
+
+/* /proc/sys/net/decnet/conf/<dev>/ */
+enum {
+	NET_DECNET_CONF_DEV_PRIORITY = 1,
+	NET_DECNET_CONF_DEV_T1 = 2,
+	NET_DECNET_CONF_DEV_T2 = 3,
+	NET_DECNET_CONF_DEV_T3 = 4,
+	NET_DECNET_CONF_DEV_COST = 5,
+	NET_DECNET_CONF_DEV_BLKSIZE = 6,
+	NET_DECNET_CONF_DEV_STATE = 7
X };
X 
X /* CTL_PROC names: */
diff -u --recursive --new-file v2.3.3/linux/include/linux/wait.h linux/include/linux/wait.h
--- v2.3.3/linux/include/linux/wait.h	Fri May 14 18:55:30 1999
+++ linux/include/linux/wait.h	Tue May 25 14:58:55 1999
@@ -8,11 +8,14 @@
X 
X #ifdef __KERNEL__
X 
-#include <asm/page.h>
-#include <asm/spinlock.h>
+#include <linux/kernel.h>
X #include <linux/list.h>
X #include <linux/stddef.h>
X 
+#include <asm/page.h>
+#include <asm/spinlock.h>
+#include <asm/processor.h>
+
X /*
X  * Temporary debugging help until all code is converted to the new
X  * waitqueue usage.
@@ -118,7 +121,6 @@
X static inline void init_waitqueue_head(wait_queue_head_t *q)
X {
X #if WAITQUEUE_DEBUG
-	__label__ __x;
X 	if (!q)
X 		WQ_BUG();
X #endif
@@ -126,7 +128,7 @@
X 	INIT_LIST_HEAD(&q->task_list);
X #if WAITQUEUE_DEBUG
X 	q->__magic = (long)&q->__magic;
-	__x: q->__creator = (long)&&__x;
+	q->__creator = (long)current_text_addr();
X #endif
X }
X 
diff -u --recursive --new-file v2.3.3/linux/include/net/decnet_call.h linux/include/net/decnet_call.h
--- v2.3.3/linux/include/net/decnet_call.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/decnet_call.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void decnet_proto_init(struct net_proto *pro);
diff -u --recursive --new-file v2.3.3/linux/include/net/dn.h linux/include/net/dn.h
--- v2.3.3/linux/include/net/dn.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dn.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,206 @@
+#ifndef _NET_DN_H
+#define _NET_DN_H
+
+#include <linux/dn.h>
+#include <asm/byteorder.h>
+
+typedef unsigned short dn_address;
+
+#define dn_ntohs(x) le16_to_cpu(x)
+#define dn_htons(x) cpu_to_le16(x)
+
+struct dn_scp                                   /* Session Control Port */
+{
+        unsigned char           state;
+#define DN_O     1                      /* Open                 */
+#define DN_CR    2                      /* Connect Receive      */
+#define DN_DR    3                      /* Disconnect Reject    */
+#define DN_DRC   4                      /* Discon. Rej. Complete*/
+#define DN_CC    5                      /* Connect Confirm      */
+#define DN_CI    6                      /* Connect Initiate     */
+#define DN_NR    7                      /* No resources         */
+#define DN_NC    8                      /* No communication     */
+#define DN_CD    9                      /* Connect Delivery     */
+#define DN_RJ    10                     /* Rejected             */
+#define DN_RUN   11                     /* Running              */
+#define DN_DI    12                     /* Disconnect Initiate  */
+#define DN_DIC   13                     /* Disconnect Complete  */
+#define DN_DN    14                     /* Disconnect Notificat */
+#define DN_CL    15                     /* Closed               */
+#define DN_CN    16                     /* Closed Notification  */
+
+        unsigned short          addrloc;
+        unsigned short          addrrem;
+        unsigned short          numdat;
+        unsigned short          numoth;
+        unsigned short          numoth_rcv;
+        unsigned short          numdat_rcv;
+        unsigned short          ackxmt_dat;
+        unsigned short          ackxmt_oth;
+        unsigned short          ackrcv_dat;
+        unsigned short          ackrcv_oth;
+        unsigned char           flowrem_sw;
+	unsigned char		flowloc_sw;
+#define DN_SEND         2
+#define DN_DONTSEND     1
+#define DN_NOCHANGE     0
+	unsigned char		accept_mode;
+	unsigned short          mss;
+
+	struct optdata_dn     conndata_in;
+	struct optdata_dn     conndata_out;
+	struct optdata_dn     discdata_in;
+	struct optdata_dn     discdata_out;
+        struct accessdata_dn  accessdata;
+
+        struct sockaddr_dn addr; /* Local address  */
+	struct sockaddr_dn peer; /* Remote address */
+
+	/*
+	 * In this case the RTT estimation is not specified in the
+	 * docs, nor is any back off algorithm. Here we follow well
+	 * known tcp algorithms with a few small variations.
+	 *
+	 * snd_window: Max number of packets we send before we wait for
+	 *             an ack to come back. This will become part of a
+	 *             more complicated scheme when we support flow
+	 *             control.
+	 *
+	 * nsp_srtt:   Round-Trip-Time (x8) in jiffies. This is a rolling
+	 *             average.
+	 * nsp_rttvar: Round-Trip-Time-Varience (x4) in jiffies. This is the
+	 *             varience of the smoothed average (but calculated in
+	 *             a simpler way than for normal statistical varience
+	 *             calculations).
+	 *
+	 * nsp_rxtshift: Backoff counter. Value is zero normally, each time
+	 *               a packet is lost is increases by one until an ack
+	 *               is received. Its used to index an array of backoff
+	 *               multipliers.
+	 */
+#define NSP_MIN_WINDOW 1
+#define NSP_MAX_WINDOW 512
+	unsigned long snd_window;
+#define NSP_INITIAL_SRTT (HZ)
+	unsigned long nsp_srtt;
+#define NSP_INITIAL_RTTVAR (HZ*3)
+	unsigned long nsp_rttvar;
+#define NSP_MAXRXTSHIFT 12
+	unsigned long nsp_rxtshift;
+
+	/*
+	 * Output queues, one for data, one for otherdata/linkservice
+	 */
+	struct sk_buff_head data_xmit_queue;
+	struct sk_buff_head other_xmit_queue;
+
+	/*
+	 * Input queue for other data
+	 */
+	struct sk_buff_head other_receive_queue;
+	int other_report;
+
+	/*
+	 * Stuff to do with the slow timer
+	 */
+	unsigned long stamp;          /* time of last transmit */
+	unsigned long persist;
+	int (*persist_fxn)(struct sock *sk);
+	unsigned long keepalive;
+	void (*keepalive_fxn)(struct sock *sk);
+
+	/*
+	 * This stuff is for the fast timer for delayed acks
+	 */
+	struct timer_list delack_timer;
+	int delack_pending;
+	void (*delack_fxn)(struct sock *sk);
+};
+
+/*
+ * src,dst : Source and Destination DECnet addresses
+ * neigh: Address from which we've just got this skb.
+ * hops : Number of hops through the network
+ * dst_port, src_port : NSP port numbers
+ * services, info : Useful data extracted from conninit messages
+ * rt_flags : Routing flags byte
+ * nsp_flags : NSP layer flags byte
+ * segsize : Size of segment
+ * segnum : Number, for data, otherdata and linkservice
+ * xmit_count : Number of times we've transmitted this skb
+ * stamp : Time stamp of first transmission, used in RTT calculations
+ * iif: Input interface number
+ *
+ * As a general policy, this structure keeps all addresses in network
+ * byte order, and all else in host byte order. Thus dst, src, dst_port
+ * src_port and neigh are in network order. All else is in host order.
+ * 
+ */
+struct dn_skb_cb {
+	unsigned short dst;
+	unsigned short src;
+	unsigned short neigh;
+	unsigned short hops;
+	unsigned short dst_port;
+	unsigned short src_port;
+	unsigned char services;
+	unsigned char info;
+	unsigned char rt_flags;
+	unsigned char nsp_flags;
+	unsigned short segsize;
+	unsigned short segnum;
+	unsigned short xmit_count;
+	unsigned long stamp;
+	int iif;
+};
+
+static __inline__ dn_address dn_eth2dn(unsigned char *ethaddr)
+{
+	return ethaddr[4] | (ethaddr[5] << 8);
+}
+
+static __inline__ dn_address dn_saddr2dn(struct sockaddr_dn *saddr)
+{
+	return *(dn_address *)saddr->sdn_nodeaddr;
+}
+
+static __inline__ void dn_dn2eth(unsigned char *ethaddr, dn_address addr)
+{
+	ethaddr[0] = 0xAA;
+	ethaddr[1] = 0x00;
+	ethaddr[2] = 0x04;
+	ethaddr[3] = 0x00;
+	ethaddr[4] = (unsigned char)(addr & 0xff);
+	ethaddr[5] = (unsigned char)(addr >> 8);
+}
+
+#define DN_MENUVER_ACC 0x01
+#define DN_MENUVER_USR 0x02
+#define DN_MENUVER_PRX 0x04
+#define DN_MENUVER_UIC 0x08
+
+extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
+extern struct sock *dn_find_by_skb(struct sk_buff *skb);
+extern unsigned short dn_alloc_port(void);
+#define DN_ASCBUF_LEN 7
+extern char *dn_addr2asc(dn_address, char *);
+extern void dn_destroy_sock(struct sock *sk);
+
+extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type);
+extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr, unsigned char *type);
+
+extern void dn_start_slow_timer(struct sock *sk);
+extern void dn_stop_slow_timer(struct sock *sk);
+extern void dn_start_fast_timer(struct sock *sk);
+extern void dn_stop_fast_timer(struct sock *sk);
+
+extern dn_address decnet_address;
+extern unsigned char decnet_ether_address[6];
+extern int decnet_node_type;
+extern int decnet_debug_level;
+extern int decnet_time_wait;
+extern int decnet_dn_count;
+extern int decnet_di_count;
+extern int decnet_dr_count;
+
+#endif /* _NET_DN_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dn_dev.h linux/include/net/dn_dev.h
--- v2.3.3/linux/include/net/dn_dev.h	Wed Dec 31 16:00:00 1969
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 40'
echo 'File patch-2.3.4 is continued in part 41'
echo 41 > _shar_seq_.tmp
#!/bin/sh
# this is part 41 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 41; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+++ linux/include/net/dn_dev.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,194 @@
+#ifndef _NET_DN_DEV_H
+#define _NET_DN_DEV_H
+
+
+struct dn_dev;
+
+struct dn_ifaddr {
+	struct dn_ifaddr *ifa_next;
+	struct dn_dev    *ifa_dev;
+	dn_address       ifa_local;
+	unsigned char    ifa_flags;
+	unsigned char    ifa_scope;
+	char             ifa_label[IFNAMSIZ];
+};
+
+#define DN_DEV_S_RU  0 /* Run - working normally   */
+#define DN_DEV_S_CR  1 /* Circuit Rejected         */
+#define DN_DEV_S_DS  2 /* Data Link Start          */
+#define DN_DEV_S_RI  3 /* Routing Layer Initialize */
+#define DN_DEV_S_RV  4 /* Routing Layer Verify     */
+#define DN_DEV_S_RC  5 /* Routing Layer Complete   */
+#define DN_DEV_S_OF  6 /* Off                      */
+#define DN_DEV_S_HA  7 /* Halt                     */
+
+
+/*
+ * The dn_dev_parms structure contains the set of parameters
+ * for each device (hence inclusion in the dn_dev structure)
+ * and an array is used to store the default types of supported
+ * device (in dn_dev.c).
+ *
+ * The type field matches the ARPHRD_ constants and is used in
+ * searching the list for supported devices when new devices
+ * come up.
+ *
+ * The mode field is used to find out if a device is broadcast,
+ * multipoint, or pointopoint. Please note that DECnet thinks
+ * different ways about devices to the rest of the kernel
+ * so the normal IFF_xxx flags are invalid here. For devices
+ * which can be any combination of the previously mentioned
+ * attributes, you can set this on a per device basis by
+ * installing an up() routine.
+ *
+ * The device state field, defines the initial state in which the
+ * device will come up. In the dn_dev structure, it is the actual
+ * state.
+ *
+ * The cost field is used in the routing algorithm.
+ *
+ * Timers:
+ * t1 - Routing timer, send routing messages when it expires
+ * t2 - Rate limit timer, min time between routing and hello messages
+ * t3 - Hello timer, send hello messages when it expires
+ *
+ * Callbacks:
+ * up() - Called to initialize device, return value can veto use of
+ *        device with DECnet.
+ * down() - Called to turn device off when it goes down
+ * timer1() - Called when timer 1 goes off
+ * timer3() - Called when timer 3 goes off
+ * setsrc() - Called for each incomming frame to set previous hop info
+ * neigh_setup() - Called to do device specific setup of neighbours
+ * 
+ * sysctl - Hook for sysctl things
+ *
+ */
+struct dn_dev_parms {
+	int type;	          /* ARPHRD_xxx                     */
+	int mode;	          /* Broadcast, Unicast, Mulitpoint */
+#define DN_DEV_BCAST  1
+#define DN_DEV_UCAST  2
+#define DN_DEV_MPOINT 4
+	int state;                /* Initial state                  */
+	int cost;	          /* Default cost of device         */
+	unsigned short blksize;   /* Block Size                     */
+	unsigned long t1;         /* Default value of t1            */
+	unsigned long t2;         /* Default value of t2            */
+	unsigned long t3;         /* Default value of t3            */
+	int priority;             /* Priority to be a router        */
+	char *name;               /* Name for sysctl                */
+	int ctl_name;             /* Index for sysctl               */
+	int  (*up)(struct device *);
+	void (*down)(struct device *);
+	void (*timer1)(struct device *);
+	void (*timer3)(struct device *);
+	int (*setsrc)(struct sk_buff *skb);
+	int (*neigh_setup)(struct neighbour *);
+	void *sysctl;
+};
+
+
+struct dn_dev {
+	struct dn_ifaddr *ifa_list;
+	struct device *dev;
+	struct dn_dev_parms parms;
+	char use_long;
+        struct timer_list timer;
+        unsigned long t3, t1;
+	struct neigh_parms *neigh_parms;
+	unsigned char addr[ETH_ALEN];
+	struct neighbour *router; /* Default router on circuit */
+	struct neighbour *peer;   /* Peer on pointopoint links */
+	unsigned long uptime;     /* Time device went up in jiffies */
+};
+
+struct dn_short_packet
+{
+	unsigned char   msgflg          __attribute__((packed));
+        unsigned short  dstnode         __attribute__((packed));
+        unsigned short  srcnode         __attribute__((packed));
+        unsigned char   forward         __attribute__((packed));
+};
+
+struct dn_long_packet
+{
+	unsigned char   msgflg          __attribute__((packed));
+        unsigned char   d_area          __attribute__((packed));
+        unsigned char   d_subarea       __attribute__((packed));
+        unsigned char   d_id[6]         __attribute__((packed));
+        unsigned char   s_area          __attribute__((packed));
+        unsigned char   s_subarea       __attribute__((packed));
+        unsigned char   s_id[6]         __attribute__((packed));
+        unsigned char   nl2             __attribute__((packed));
+        unsigned char   visit_ct        __attribute__((packed));
+        unsigned char   s_class         __attribute__((packed));
+        unsigned char   pt              __attribute__((packed));
+};
+
+/*------------------------- DRP - Routing messages ---------------------*/
+
+        struct endnode_hello_message
+        {
+                unsigned char   msgflg          __attribute__((packed));
+                unsigned char   tiver[3]        __attribute__((packed));
+                unsigned char   id[6]           __attribute__((packed));
+                unsigned char   iinfo           __attribute__((packed));
+                unsigned short  blksize         __attribute__((packed));
+                unsigned char   area            __attribute__((packed));
+                unsigned char   seed[8]         __attribute__((packed));
+                unsigned char   neighbor[6]     __attribute__((packed));
+                unsigned short  timer           __attribute__((packed));
+                unsigned char   mpd             __attribute__((packed));
+                unsigned char   datalen         __attribute__((packed));
+                unsigned char   data[2]         __attribute__((packed));
+        };
+        struct rtnode_hello_message
+        {
+                unsigned char   msgflg          __attribute__((packed));
+                unsigned char   tiver[3]        __attribute__((packed));
+                unsigned char   id[6]           __attribute__((packed));
+                unsigned char   iinfo           __attribute__((packed));
+                unsigned short  blksize         __attribute__((packed));
+                unsigned char   priority        __attribute__((packed));
+                unsigned char   area            __attribute__((packed));
+                unsigned short  timer           __attribute__((packed));
+                unsigned char   mpd             __attribute__((packed));
+        };
+
+
+extern void dn_dev_init(void);
+extern void dn_dev_cleanup(void);
+
+extern int dn_dev_ioctl(unsigned int cmd, void *arg);
+
+extern void dn_dev_devices_off(void);
+extern void dn_dev_devices_on(void);
+
+extern void dn_dev_init_pkt(struct sk_buff *skb);
+extern void dn_dev_veri_pkt(struct sk_buff *skb);
+extern void dn_dev_hello(struct sk_buff *skb);
+
+extern void dn_dev_up(struct device *);
+extern void dn_dev_down(struct device *);
+
+extern struct device *decnet_default_device;
+
+static __inline__ int dn_dev_islocal(struct device *dev, dn_address addr)
+{
+	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_ifaddr *ifa;
+
+	if (dn_db == NULL) {
+		printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
+		return 0;
+	}
+
+	for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next)
+		if ((addr ^ ifa->ifa_local) == 0)
+			return 1;
+
+	return 0;
+}
+
+#endif /* _NET_DN_DEV_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dn_fib.h linux/include/net/dn_fib.h
--- v2.3.3/linux/include/net/dn_fib.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dn_fib.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,83 @@
+#ifndef _NET_DN_FIB_H
+#define _NET_DN_FIB_H
+
+#ifdef CONFIG_DECNET_ROUTER
+
+
+struct dn_fib_res {
+	dn_address res_addr;
+	dn_address res_mask;
+	int res_ifindex;
+	int res_proto;
+	int res_cost;
+	int res_type;
+	struct dn_fib_node *res_fn;
+	struct dn_fib_action *res_fa;
+};
+
+struct dn_fib_action {
+	struct dn_fib_action *fa_next;
+	dn_address fa_key;
+	dn_address fa_mask;
+	int fa_ifindex;
+	int fa_proto;
+	int fa_cost;
+	int fa_type;
+	union {
+		struct neighbour *fau_neigh;	/* Normal route */
+		int fau_error;			/* Reject       */
+		int fau_table;			/* Throw        */
+	} fa_u;
+#define fa_neigh fa_u.fau_neigh
+#define fa_error fa_u.fau_error
+#define fa_table fa_u.fau_table
+};
+
+struct dn_fib_node {
+	struct dn_fib_node *fn_up;
+	dn_address fn_cmpmask;
+	dn_address fn_key;
+	int fn_shift;
+	struct dn_fib_action *fn_action;
+	struct dn_fib_node *fn_children[2];
+};
+
+#define DN_FIB_NEXT(fibnode, key) ((fibnode)->fn_children[((key) ^ (fibnode)->fn_cmpmask) >> (fibnode)->fn_shift]) 
+
+struct dn_fib_walker_t;
+
+struct dn_fib_table {
+	int n;
+	unsigned long count;
+	struct dn_fib_node *root;
+
+	int (*insert)(struct dn_fib_table *t, struct dn_fib_action *fa);
+	int (*delete)(struct dn_fib_table *t, struct dn_fib_action *fa);
+	int (*lookup)(struct dn_fib_table *t, struct dn_fib_res *res);
+	int (*walk)(struct dn_fib_walker_t *fwt);
+#ifdef CONFIG_RTNETLINK
+	int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
+#endif /* CONFIG_RTNETLINK */
+};
+
+struct dn_fib_walker_t {
+	struct dn_fib_table *table;
+	void *arg;
+	int (*fxn)(struct dn_fib_walker_t *fwt, struct dn_fib_node *n);
+};
+
+extern void dn_fib_init(void);
+extern void dn_fib_cleanup(void);
+
+extern int dn_fib_rt_message(struct sk_buff *skb);
+extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+
+#ifdef CONFIG_RTNETLINK
+extern int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
+extern int dn_fib_rtm_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+#endif /* CONFIG_RTNETLINK */
+#endif /* CONFIG_DECNET_ROUTER */
+
+#endif /* _NET_DN_FIB_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dn_neigh.h linux/include/net/dn_neigh.h
--- v2.3.3/linux/include/net/dn_neigh.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dn_neigh.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,29 @@
+#ifndef _NET_DN_NEIGH_H
+#define _NET_DN_NEIGH_H
+
+/*
+ * The position of the first two fields of
+ * this structure are critical - SJW
+ */
+struct dn_neigh {
+        struct neighbour n;
+        unsigned char addr[ETH_ALEN];
+        unsigned long flags;
+#define DN_NDFLAG_R1    0x0001 /* Router L1      */
+#define DN_NDFLAG_R2    0x0002 /* Router L2      */
+#define DN_NDFLAG_P3    0x0004 /* Phase III Node */
+        unsigned long blksize;
+	unsigned char priority;
+};
+
+extern void dn_neigh_init(void);
+extern void dn_neigh_cleanup(void);
+extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr);
+extern void dn_neigh_router_hello(struct sk_buff *skb);
+extern void dn_neigh_endnode_hello(struct sk_buff *skb);
+extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
+extern int dn_neigh_elist(struct device *dev, unsigned char *ptr, int n);
+
+extern struct neigh_table dn_neigh_table;
+
+#endif /* _NET_DN_NEIGH_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dn_nsp.h linux/include/net/dn_nsp.h
--- v2.3.3/linux/include/net/dn_nsp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dn_nsp.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,194 @@
+#ifndef _NET_DN_NSP_H
+#define _NET_DN_NSP_H
+/******************************************************************************
+    (c) 1995-1998 E.M. Serrat		emse...@geocities.com
+    
+    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
+    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.
+*******************************************************************************/
+/* dn_nsp.c functions prototyping */
+
+extern void dn_nsp_send_data_ack(struct sock *sk);
+extern void dn_nsp_send_oth_ack(struct sock *sk);
+extern void dn_nsp_delayed_ack(struct sock *sk);
+extern void dn_send_conn_ack(struct sock *sk);
+extern void dn_send_conn_conf(struct sock *sk);
+extern void dn_send_disc(struct sock *sk, unsigned char type, unsigned short reason);
+extern void dn_nsp_send_lnk(struct sock *sk, unsigned short flags);
+extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
+
+extern void dn_nsp_output(struct sock *sk);
+extern int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum);
+extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int oob);
+extern unsigned long dn_nsp_persist(struct sock *sk);
+extern int dn_nsp_xmit_timeout(struct sock *sk);
+
+extern int dn_nsp_rx(struct sk_buff *);
+extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+
+extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri);
+extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, int *size, int noblock, int *err);
+
+#define NSP_REASON_NR 1
+#define NSP_REASON_DC 42
+#define NSP_REASON_NL 41
+
+#define NSP_DISCINIT 0x38
+#define NSP_DISCCONF 0x48
+
+/*------------------------- NSP - messages ------------------------------*/
+/* Data Messages */
+/*---------------*/
+
+/* Data Messages    (data segment/interrupt/link service)               */
+
+        struct nsp_data_seg_msg
+        {
+                unsigned char   msgflg          __attribute__((packed));
+                unsigned short  dstaddr         __attribute__((packed));
+                unsigned short  srcaddr         __attribute__((packed));
+        };
+
+        struct nsp_data_opt_msg
+        {
+                unsigned short  acknum          __attribute__((packed));
+                unsigned short  segnum          __attribute__((packed));
+                unsigned short  lsflgs          __attribute__((packed));
+        };
+
+        struct nsp_data_opt_msg1
+        {
+                unsigned short  acknum          __attribute__((packed));
+                unsigned short  segnum          __attribute__((packed));
+        };
+
+/* Acknowledgment Messages */
+/*-------------------------*/
+
+/* Acknowledgment Messages (data/other data)                             */
+
+        struct  nsp_data_ack_msg
+        {
+                unsigned char   msgflg          __attribute__((packed));
+                unsigned short  dstaddr         __attribute__((packed));
+                unsigned short  srcaddr         __attribute__((packed));
+                unsigned short  acknum          __attribute__((packed));
+        };
+
+/* Connect Acknowledgment Message */
+
+        struct  nsp_conn_ack_msg
+        {
+                unsigned char   msgflg          __attribute__((packed));
+                unsigned short  dstaddr         __attribute__((packed));
+        };
+
+/* Control Messages */
+/*------------------*/
+
+/* Connect Initiate/Retransmit Initiate/Connect Confirm */
+
+        struct  nsp_conn_init_msg
+        {
+                unsigned char   msgflg          __attribute__((packed));
+#define         NSP_CI          0x18            /* Connect Initiate     */
+#define         NSP_RCI         0x68            /* Retrans. Conn Init   */
+                unsigned short  dstaddr         __attribute__((packed));
+                unsigned short  srcaddr         __attribute__((packed));
+                unsigned char   services        __attribute__((packed));
+#define         NSP_FC_NONE     0x00            /* Flow Control None    */
+#define         NSP_FC_SRC      0x04            /* Seg Req. Count       */
+#define         NSP_FC_SCMC     0x08            /* Sess. Control Mess   */
+                unsigned char   info            __attribute__((packed));
+                unsigned short  segsize         __attribute__((packed));
+        };
+
+/* Disconnect Initiate/Disconnect Confirm */
+
+        struct  nsp_disconn_init_msg
+        {
+                unsigned char   msgflg          __attribute__((packed));
+                unsigned short  dstaddr         __attribute__((packed));
+                unsigned short  srcaddr         __attribute__((packed));
+                unsigned short  reason          __attribute__((packed));
+        };
+
+
+/*------------------------- SCP - messages ------------------------------*/
+
+        struct  srcobj_fmt
+        {
+                char            format          __attribute__((packed));
+                unsigned char   task            __attribute__((packed));
+                unsigned short  grpcode         __attribute__((packed));
+                unsigned short  usrcode         __attribute__((packed));
+                char            dlen            __attribute__((packed));
+        };
+
+/*
+ * A collection of functions for manipulating the sequence
+ * numbers used in NSP. Similar in operation to the functions
+ * of the same name in TCP.
+ */
+static __inline__ int before(unsigned short seq1, unsigned short seq2)
+{
+        seq1 &= 0x0fff;
+        seq2 &= 0x0fff;
+
+        return (int)((seq1 - seq2) & 0x0fff) > 2048;
+}
+
+
+static __inline__ int after(unsigned short seq1, unsigned short seq2)
+{
+        seq1 &= 0x0fff;
+        seq2 &= 0x0fff;
+
+        return (int)((seq2 - seq1) & 0x0fff) > 2048;
+}
+
+static __inline__ int equal(unsigned short seq1, unsigned short seq2)
+{
+        return ((seq1 ^ seq2) & 0x0fff) == 0;
+}
+
+static __inline__ int before_or_equal(unsigned short seq1, unsigned short seq2)
+{
+	return (before(seq1, seq2) || equal(seq1, seq2));
+}
+
+static __inline__ void seq_add(unsigned short *seq, unsigned short off)
+{
+        *seq += off;
+        *seq &= 0x0fff;
+}
+
+static __inline__ int seq_next(unsigned short seq1, unsigned short seq2)
+{
+	return (((seq2&0x0fff) - (seq1&0x0fff)) == 1);
+}
+
+/*
+ * Can we delay the ack ?
+ */
+static __inline__ int sendack(unsigned short seq)
+{
+        return (int)((seq & 0x1000) ? 0 : 1);
+}
+
+/*
+ * Is socket congested ?
+ */
+static __inline__ int dn_congested(struct sock *sk)
+{
+        return atomic_read(&sk->rmem_alloc) > (sk->rcvbuf >> 1);
+}
+
+#endif /* _NET_DN_NSP_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dn_raw.h linux/include/net/dn_raw.h
--- v2.3.3/linux/include/net/dn_raw.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dn_raw.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,17 @@
+#ifndef _NET_DN_RAW_H
+#define _NET_DN_RAW_H
+
+#ifdef CONFIG_DECNET_RAW
+
+extern struct proto_ops dn_raw_proto_ops;
+
+extern void dn_raw_rx_nsp(struct sk_buff *skb);
+extern void dn_raw_rx_routing(struct sk_buff *skb);
+
+#ifdef CONFIG_DECNET_MOP
+extern void dn_raw_rx_mop(struct sk_buff *skb);
+#endif /* CONFIG_DECNET_MOP */
+
+#endif /* CONFIG_DECNET_RAW */
+
+#endif /* _NET_DN_RAW_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dn_route.h linux/include/net/dn_route.h
--- v2.3.3/linux/include/net/dn_route.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dn_route.h	Wed May 26 09:36:35 1999
@@ -0,0 +1,74 @@
+#ifndef _NET_DN_ROUTE_H
+#define _NET_DN_ROUTE_H
+
+/******************************************************************************
+    (c) 1995-1998 E.M. Serrat		emse...@geocities.com
+    
+    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
+    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.
+*******************************************************************************/
+/* dn_route.c functions prototyping */
+extern void dn_send_skb(struct sk_buff *);
+extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri);
+extern int dn_route_output(struct sock *sk);
+
+/* Masks for flags field */
+#define DN_RT_F_PID 0x07 /* Mask for packet type                      */
+#define DN_RT_F_PF  0x80 /* Padding Follows                           */
+#define DN_RT_F_VER 0x40 /* Version =0 discard packet if ==1          */
+#define DN_RT_F_IE  0x20 /* Intra Ethernet, Reserved in short pkt     */
+#define DN_RT_F_RTS 0x10 /* Packet is being returned to sender        */
+#define DN_RT_F_RQR 0x08 /* Return packet to sender upon non-delivery */
+
+/* Mask for types of routing packets */
+#define DN_RT_PKT_MSK   0x06
+/* Types of routing packets */
+#define DN_RT_PKT_SHORT 0x02 /* Short routing packet */
+#define DN_RT_PKT_LONG  0x06 /* Long routing packet  */
+
+/* Mask for control/routing selection */
+#define DN_RT_PKT_CNTL  0x01 /* Set to 1 if a control packet  */
+/* Types of control packets */
+#define DN_RT_CNTL_MSK  0x0f /* Mask for control packets      */
+#define DN_RT_PKT_INIT  0x01 /* Initialisation packet         */
+#define DN_RT_PKT_VERI  0x03 /* Verification Message          */
+#define DN_RT_PKT_HELO  0x05 /* Hello and Test Message        */
+#define DN_RT_PKT_L1RT  0x07 /* Level 1 Routing Message       */
+#define DN_RT_PKT_L2RT  0x09 /* Level 2 Routing Message       */
+#define DN_RT_PKT_ERTH  0x0b /* Ethernet Router Hello         */
+#define DN_RT_PKT_EEDH  0x0d /* Ethernet EndNode Hello        */
+
+/* Values for info field in hello message */
+#define DN_RT_INFO_TYPE 0x03 /* Type mask                     */
+#define DN_RT_INFO_L1RT 0x02 /* L1 Router                     */
+#define DN_RT_INFO_L2RT 0x01 /* L2 Router                     */
+#define DN_RT_INFO_ENDN 0x03 /* EndNode                       */
+#define DN_RT_INFO_VERI 0x04 /* Verification Reqd.            */
+#define DN_RT_INFO_RJCT 0x08 /* Reject Flag, Reserved         */
+#define DN_RT_INFO_VFLD 0x10 /* Verification Failed, Reserved */
+#define DN_RT_INFO_NOML 0x20 /* No Multicast traffic accepted */
+#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested            */
+
+
+struct dn_route {
+	union {
+		struct dst_entry dst;
+		struct dn_route *rt_next;
+	} u;
+	unsigned short rt_saddr;
+	unsigned short rt_daddr;
+	int rt_iif;
+	int rt_oif;
+};
+
+extern void dn_route_init(void);
+extern void dn_route_cleanup(void);
+
+#endif /* _NET_DN_ROUTE_H */
diff -u --recursive --new-file v2.3.3/linux/include/net/dst.h linux/include/net/dst.h
--- v2.3.3/linux/include/net/dst.h	Tue May 11 13:05:02 1999
+++ linux/include/net/dst.h	Wed May 26 18:14:37 1999
@@ -77,9 +77,6 @@
X 
X #ifdef __KERNEL__
X 
-extern struct dst_entry * dst_garbage_list;
-extern atomic_t	dst_total;
-
X extern __inline__
X struct dst_entry * dst_clone(struct dst_entry * dst)
X {
diff -u --recursive --new-file v2.3.3/linux/include/net/ip.h linux/include/net/ip.h
--- v2.3.3/linux/include/net/ip.h	Tue May 11 13:05:15 1999
+++ linux/include/net/ip.h	Mon May 31 22:07:43 1999
@@ -83,7 +83,6 @@
X  *	Functions provided by ip.c
X  */
X 
-extern int		ip_ioctl(struct sock *sk, int cmd, unsigned long arg);
X extern void		ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
X 					      u32 saddr, u32 daddr,
X 					      struct ip_options *opt);
diff -u --recursive --new-file v2.3.3/linux/include/net/ip_masq.h linux/include/net/ip_masq.h
--- v2.3.3/linux/include/net/ip_masq.h	Tue May 11 13:05:13 1999
+++ linux/include/net/ip_masq.h	Sat May 29 11:06:06 1999
@@ -231,24 +231,6 @@
X 
X extern rwlock_t __ip_masq_lock;
X 
-#ifdef __SMP__
-#define read_lock_bh(lock) 	do { start_bh_atomic(); read_lock(lock); \
-					} while (0)
-#define read_unlock_bh(lock)	do { read_unlock(lock); end_bh_atomic(); \
-					} while (0)
-#define write_lock_bh(lock)	do { start_bh_atomic(); write_lock(lock); \
-					} while (0)
-#define write_unlock_bh(lock)	do { write_unlock(lock); end_bh_atomic(); \
-					} while (0)
-#else
-#define read_lock_bh(lock)	start_bh_atomic()
-#define read_unlock_bh(lock)	end_bh_atomic()
-#define write_lock_bh(lock)	start_bh_atomic()
-#define write_unlock_bh(lock)	end_bh_atomic()
-#endif 
-/*
- *
- */
X 
X /*
X  *	Debugging stuff
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/crc.h linux/include/net/irda/crc.h
--- v2.3.3/linux/include/net/irda/crc.h	Wed Jan 20 11:05:33 1999
+++ linux/include/net/irda/crc.h	Sun May 30 10:27:04 1999
@@ -6,25 +6,28 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Tue Dec 15 22:18:53 1998
+ * Modified at:   Sun May  2 20:25:23 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  ********************************************************************/
X 
-#ifndef IR_CRC_H
-#define IR_CRC_H
+#ifndef IRDA_CRC_H
+#define IRDA_CRC_H
X 
X #include <linux/types.h>
X 
X #define INIT_FCS  0xffff   /* Initial FCS value */
X #define GOOD_FCS  0xf0b8   /* Good final FCS value */
X 
+extern __u16 const irda_crc16_table[];
+
X /* Recompute the FCS with one more character appended. */
-#define IR_FCS(fcs, c) (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff])
+static inline __u16 irda_fcs(__u16 fcs, __u8 c)
+{
+	return (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff]);
+}
X 
X /* Recompute the FCS with len bytes appended. */
X unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len);
-
-extern __u16 const irda_crc16_table[];
X 
X #endif
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h
--- v2.3.3/linux/include/net/irda/dongle.h	Sun Mar  7 15:26:43 1999
+++ linux/include/net/irda/dongle.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Sat Feb  6 07:37:49 1999
+ * Modified at:   Mon May 10 14:51:06 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 
@@ -26,7 +26,6 @@
X #define DONGLE_H
X 
X #include <net/irda/qos.h>
-#include <net/irda/irda_device.h>
X 
X /* These are the currently known dongles */
X typedef enum {
@@ -35,7 +34,10 @@
X 	ACTISYS_DONGLE,
X 	ACTISYS_PLUS_DONGLE,
X 	GIRBIL_DONGLE,
+	LITELINK_DONGLE,
X } DONGLE_T;
+
+struct irda_device;
X 
X struct dongle {
X 	DONGLE_T type;
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h
--- v2.3.3/linux/include/net/irda/ircomm_common.h	Fri May 14 18:55:30 1999
+++ linux/include/net/irda/ircomm_common.h	Sun May 30 10:27:04 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Takahide Higuchi <thig...@pluto.dti.ne.jp>
X  *
- *     Copyright (c) 1998, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
+ *     Copyright (c) 1998-1999, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
X  *     All Rights Reserved.
X  *
X  *     This program is free software; you can redistribute it and/or
@@ -78,7 +78,7 @@
X #define IRCOMM_MAGIC            0x434f4d4d
X #define COMM_INIT_CTRL_PARAM    3          /* length of initial control parameters */
X #define COMM_HEADER             1          /* length of clen field */
-#define COMM_HEADER_SIZE        (LAP_HEADER+LMP_HEADER+TTP_HEADER+COMM_HEADER)
+#define COMM_HEADER_SIZE        (TTP_MAX_HEADER+COMM_HEADER)
X #define COMM_DEFAULT_DATA_SIZE  64
X #define IRCOMM_MAX_CONNECTION   1          /* Don't change for now */
X 
@@ -167,7 +167,7 @@
X #define LSR_BI     0x01    /* Break interrupt indicator */
X 
X 
-struct ircomm_cb{
+struct ircomm_cb {
X 	int magic;
X 	int state;          /* Current state of IrCOMM layer: 
X 			     *  DISCOVERY,COMM_IDLE, COMM_WAITR,
@@ -178,7 +178,8 @@
X 	int ttp_stop;
X 
X 	int max_txbuff_size;          
-	__u32 maxsdusize;
+	__u32 max_sdu_size;
+	__u8 max_header_size;
X 
X  	__u32 daddr;        /* Device address of the peer device */ 
X 	__u32 saddr;
@@ -211,8 +212,6 @@
X 	int                 pending_control_tuples;
X 	int                 ignored_control_tuples;
X 
-
-
X 	__u8 pi ;            /* instruction of control channel*/ 
X 
X 	__u8 port_type;
@@ -252,8 +251,6 @@
X 	char port_name[33];
X 	int port_name_critical;
X };
-
-
X 
X void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype);
X void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.3.3/linux/include/net/irda/irda.h	Fri May 14 18:55:30 1999
+++ linux/include/net/irda/irda.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Wed Apr 21 17:49:00 1999
+ * Modified at:   Mon May 10 09:51:13 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 
@@ -109,6 +109,8 @@
X 	
X 	__u32 max_sdu_size_rx;
X 	__u32 max_sdu_size_tx;
+	__u32 max_data_size;
+	__u8  max_header_size;
X 	struct qos_info qos_tx;
X 
X 	__u16 mask;           /* Hint bits mask */
@@ -225,10 +227,10 @@
X 	int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb);
X 	void (*connect_confirm)(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 	void (*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 	void (*disconnect_indication)(void *instance, void *sap, 
X 				      LM_REASON reason, struct sk_buff *);
X 	void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow);
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.3.3/linux/include/net/irda/irda_device.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/irda_device.h	Sun May 30 10:27:04 1999
@@ -4,24 +4,29 @@
X  * Version:       
X  * Description:   
X  * Status:        Experimental.
- * Author:        Haris Zukanovic <ha...@stud.cs.uit.no>
+ * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Tue Apr 20 11:06:28 1999
+ * Modified at:   Mon May 10 15:46:02 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1998 Haris Zukanovic, <ha...@stud.cs.uit.no>
- *     Copyright (c) 1998 Dag Brattli, <da...@cs.uit.no>
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
X  *     Copyright (c) 1998 Thomas Davis, <rat...@radiks.net>,
- *     All Rights Reserved.
- *      
+ *     Copyright (c) 1998 Haris Zukanovic, <ha...@stud.cs.uit.no>
+ *
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 Haris Zukanovic nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ * 
+ *     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  ********************************************************************/
X 
@@ -35,6 +40,7 @@
X 
X #include <net/irda/irda.h>
X #include <net/irda/qos.h>
+#include <net/irda/dongle.h>
X #include <net/irda/irqueue.h>
X #include <net/irda/irlap_frame.h>
X 
@@ -52,6 +58,11 @@
X #define IO_XMIT 0x01
X #define IO_RECV 0x02
X 
+struct dongle_q {
+	QUEUE q;
+	struct dongle *dongle;
+};
+
X /* Chip specific info */
X struct chipio_t {
X         int iobase, iobase2;  /* IO base */
@@ -111,6 +122,8 @@
X 	struct iobuff_t tx_buff;
X 	struct iobuff_t rx_buff;
X 
+	struct dongle *dongle; /* Dongle driver */
+
X 	/* spinlock_t lock; */ /* For serializing operations */
X 	
X 	/* Media busy stuff */
@@ -120,7 +133,8 @@
X 	/* Callbacks for driver specific implementation */
X         void (*change_speed)(struct irda_device *driver, int baud);
X  	int  (*is_receiving)(struct irda_device *);    /* receiving? */
-	/* int (*is_tbusy)(struct irda_device *); */   /* transmitting? */
+	void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts);
+	int  (*raw_write)(struct irda_device *idev, __u8 *buf, int len);
X 	void (*wait_until_sent)(struct irda_device *);
X 	void (*set_caddr)(struct irda_device *);      /* Set connection addr */
X };
@@ -142,6 +156,9 @@
X 
X inline struct qos_info *irda_device_get_qos(struct irda_device *self);
X int irda_device_txqueue_empty(struct irda_device *self);
+void irda_device_init_dongle(struct irda_device *self, int type);
+void irda_device_unregister_dongle(struct dongle *dongle);
+int irda_device_register_dongle(struct dongle *dongle);
X 
X int irda_device_setup(struct device *dev);
X 
@@ -153,7 +170,7 @@
X  *    Utility function for getting the minimum turnaround time out of 
X  *    the skb, where it has been hidden in the cb field.
X  */
-inline static __u16 irda_get_mtt(struct sk_buff *skb)
+extern inline __u16 irda_get_mtt(struct sk_buff *skb)
X {
X 	__u16 mtt;
X 
@@ -165,6 +182,23 @@
X 	ASSERT(mtt <= 10000, return 10000;);
X 	
X 	return mtt;
+}
+
+extern inline void irda_device_set_dtr_rts(struct irda_device *self, int dtr,
+					   int rts)
+{
+	if (self->set_dtr_rts)
+		self->set_dtr_rts(self, dtr, rts);
+}
+
+extern inline int irda_device_raw_write(struct irda_device *self, __u8 *buf,
+					int len)
+{
+	int ret = -1;
+
+	if (self->raw_write)
+		ret = self->raw_write(self, buf, len);
+	return ret;
X }
X 
X #endif
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.3.3/linux/include/net/irda/iriap.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/iriap.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Wed Apr 21 16:37:21 1999
+ * Modified at:   Sun May  9 10:56:57 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 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 
@@ -81,6 +81,8 @@
X 	CONFIRM_CALLBACK confirm;
X 	void *priv;
X 
+	__u8 max_header_size;
+	
X 	struct timer_list watchdog_timer;
X };
X 
@@ -92,8 +94,6 @@
X void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
X 
X void iriap_send_ack( struct iriap_cb *self);
-void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *skb);
X void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb);
X 
X void iriap_register_server(void);
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h
--- v2.3.3/linux/include/net/irda/irlan_common.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/irlan_common.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,11 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 14:30:37 1999
+ * Modified at:   Sun May  9 11:45:33 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 
@@ -98,7 +99,7 @@
X #define IRLAN_SHORT  1
X #define IRLAN_ARRAY  2
X 
-#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_MAX_HEADER)
X 
X /*
X  *  IrLAN client
@@ -109,7 +110,10 @@
X 	int open_retries;
X 
X 	struct tsap_cb *tsap_ctrl;
+	__u32 max_sdu_size;
+	__u8  max_header_size;
X 	
+	int access_type;         /* Access type of provider */
X 	__u8 reconnect_key[255];
X 	__u8 key_len;
X 	
@@ -130,6 +134,8 @@
X 	int state;
X 	
X 	struct tsap_cb *tsap_ctrl;
+	__u32 max_sdu_size;
+	__u8  max_header_size;
X 
X 	/*
X 	 *  Store some values here which are used by the provider to parse
@@ -140,42 +146,45 @@
X 	int filter_mode;
X 	int filter_operation;
X 	int filter_entry;
-
+	int access_type;     /* Access type */
X 	__u16 send_arb_val;
X 
X 	__u8 mac_address[6]; /* Generated MAC address for peer device */
X };
X 
X /*
- *  IrLAN
+ *  IrLAN control block
X  */
X struct irlan_cb {
X 	QUEUE queue; /* Must be first */
X 
X 	int    magic;
X 	char   ifname[9];
-	struct device dev;  /* Ethernet device structure*/
+	struct device dev;        /* Ethernet device structure*/
X 	struct enet_statistics stats;
X 
-	__u32 saddr;        /* Source devcie address */
-	__u32 daddr;        /* Destination device address */
+	__u32 saddr;              /* Source devcie address */
+	__u32 daddr;              /* Destination device address */
X 	int   netdev_registered;
X 	int   notify_irmanager;
X 	
-	int media;          /* Media type */
-	int access_type;    /* Currently used access type */
-	__u8 version[2];    /* IrLAN version */
+	int media;                /* Media type */
+	__u8 version[2];          /* IrLAN version */
X 	
X 	struct tsap_cb *tsap_data;
X 
-	int  use_udata;  /* Use Unit Data transfers */
+	int  master;              /* Master instance? */
+	int  use_udata;           /* Use Unit Data transfers */
X 
-	__u8 stsap_sel_data; /* Source data TSAP selector */
-	__u8 dtsap_sel_data; /* Destination data TSAP selector */
-	__u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */
+	__u8 stsap_sel_data;      /* Source data TSAP selector */
+	__u8 dtsap_sel_data;      /* Destination data TSAP selector */
+	__u8 dtsap_sel_ctrl;      /* Destination ctrl TSAP selector */
X 
-	struct irlan_client_cb client;     /* Client specific fields */
+	struct irlan_client_cb   client;   /* Client specific fields */
X 	struct irlan_provider_cb provider; /* Provider specific fields */
+
+	__u32 max_sdu_size;
+	__u8  max_header_size;
X 	
X 	struct timer_list watchdog_timer;
X };
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irlan_provider.h linux/include/net/irda/irlan_provider.h
--- v2.3.3/linux/include/net/irda/irlan_provider.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/irlan_provider.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 14:29:16 1999
+ * Modified at:   Sun May  9 12:26:11 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 
@@ -36,13 +36,7 @@
X 					       LM_REASON reason, 
X 					       struct sk_buff *skb);
X 
-void irlan_provider_ctrl_data_indication(void *instance, void *sap,
-					 struct sk_buff *skb);
X 
-void irlan_provider_connect_indication(void *instance, void *sap, 
-				       struct qos_info *qos, 
-				       __u32 max_sdu_size,
-				       struct sk_buff *skb);
X void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *);
X 
X int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb);
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.3.3/linux/include/net/irda/irlap.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/irlap.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Apr 23 09:51:15 1999
+ * Modified at:   Sun May  9 11:38:18 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 
@@ -42,11 +42,11 @@
X #define LAP_COMP_HEADER 1  /* IrLAP Compression Header */
X 
X #ifdef CONFIG_IRDA_COMPRESSION
-#  define LAP_HEADER  (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER)
+#  define LAP_MAX_HEADER  (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER)
X #  define IRDA_COMPRESSED 1
X #  define IRDA_NORMAL     0
X #else
-#define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
+#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
X #endif
X 
X #define BROADCAST  0xffffffff /* Broadcast device address */
@@ -138,7 +138,7 @@
X 
X 	__u8    vs;           /* Next frame to be sent */
X 	__u8    vr;           /* Next frame to be received */
-	int     tmp;
+/* 	int     tmp; */
X 	__u8    va;           /* Last frame acked */
X  	int     window;       /* Nr of I-frames allowed to send */
X 	int     window_size;  /* Current negotiated window size */
@@ -155,8 +155,7 @@
X  	__u8    s;           /* Current slot */
X 	int     frame_sent;  /* Have we sent reply? */
X 
-	int discovery_count;
-	hashbin_t *discovery_log;
+	hashbin_t   *discovery_log;
X  	discovery_t *discovery_cmd;
X 
X 	struct qos_info qos_tx;    /* QoS requested by peer */
@@ -226,5 +225,10 @@
X void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *);
X void irlap_apply_default_connection_parameters(struct irlap_cb *self);
X void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *);
+
+extern inline __u8 irlap_get_header_size(struct irlap_cb *self)
+{
+	return 2;
+}
X 
X #endif
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.3.3/linux/include/net/irda/irlmp.h	Sat Apr 24 17:50:06 1999
+++ linux/include/net/irda/irlmp.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Fri Apr 23 09:15:07 1999
+ * Modified at:   Sun May  9 11:01:34 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,7 +52,7 @@
X 
X #define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
X #define LMP_CONTROL_HEADER  4
-#define LMP_MAX_HEADER      (LAP_HEADER+LMP_HEADER)
+#define LMP_MAX_HEADER      (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
X 
X #define LM_MAX_CONNECTIONS  10
X 
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irlpt_common.h linux/include/net/irda/irlpt_common.h
--- v2.3.3/linux/include/net/irda/irlpt_common.h	Fri May 14 18:55:30 1999
+++ linux/include/net/irda/irlpt_common.h	Sun May 30 10:27:04 1999
@@ -158,7 +158,8 @@
X 	struct miscdevice ir_dev; /* used to register the misc device. */
X 
X 	int count;                /* open count */
-	int irlap_data_size;	/* max frame size we can send */
+	int max_data_size;	/* max frame size we can send */
+	int max_header_size;    /* how much header space is needed */
X 	int pkt_count;		/* how many packets are queued up */
X 
X 	wait_queue_head_t read_wait;	/* wait queues */
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.3/linux/include/net/irda/irport.h	Wed Jan 20 11:05:33 1999
+++ linux/include/net/irda/irport.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Thu Jan  7 14:17:31 1999
+ * Modified at:   Mon May 10 22:12:56 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997, 1998 Dag Brattli <da...@cs.uit.no>
+ *     Copyright (c) 1997, 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 
@@ -49,13 +49,13 @@
X 
X #define FRAME_MAX_SIZE 2048
X 
-void irport_close( int iobase);
-int  irport_open( int iobase);
-int  irport_detect(struct irda_device *idev);
+void irport_start(int iobase);
+void irport_stop(int iobase);
+int  irport_probe(int iobase);
X 
-void irport_change_speed( int iobase, int speed);
+void irport_change_speed(struct irda_device *idev, int speed);
X void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
X 
-int  irport_hard_xmit( struct sk_buff *skb, struct device *dev);
+int  irport_hard_xmit(struct sk_buff *skb, struct device *dev);
X 
X #endif
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.3.3/linux/include/net/irda/irttp.h	Sat Apr 24 17:50:06 1999
+++ linux/include/net/irda/irttp.h	Sun May 30 10:27:04 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:19:56 1999
+ * Modified at:   Mon May 10 19:14:51 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 
@@ -36,7 +36,8 @@
X 
X #define TTP_MAX_CONNECTIONS    LM_MAX_CONNECTIONS
X #define TTP_HEADER             1
-#define TTP_HEADER_WITH_SAR    6
+#define TTP_MAX_HEADER         (TTP_HEADER + LMP_MAX_HEADER)
+#define TTP_SAR_HEADER         5
X #define TTP_PARAMETERS         0x80
X #define TTP_MORE               0x80
X 
@@ -61,8 +62,6 @@
X 	QUEUE queue;          /* For linking it into the hashbin */
X 	int  magic;           /* Just in case */
X 
-	int max_seg_size;     /* Max data that fit into an IrLAP frame */
-
X 	__u8 stsap_sel;       /* Source TSAP */
X 	__u8 dtsap_sel;       /* Destination TSAP */
X 
@@ -88,6 +87,9 @@
X 	struct irda_statistics stats;
X 	struct timer_list todo_timer; 
X 	
+	__u32 max_seg_size;     /* Max data that fit into an IrLAP frame */
+	__u8  max_header_size;
+
X 	int   rx_sdu_busy;     /* RxSdu.busy */
X 	__u32 rx_sdu_size;     /* Current size of a partially received frame */
X 	__u32 rx_max_sdu_size; /* Max receive user data size */
@@ -120,8 +122,6 @@
X 			  __u32 saddr, __u32 daddr,
X 			  struct qos_info *qos, __u32 max_sdu_size, 
X 			  struct sk_buff *userdata);
-void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *skb);
X void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
X 			    struct sk_buff *userdata);
X struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h
--- v2.3.3/linux/include/net/irda/irtty.h	Sun Mar  7 15:26:44 1999
+++ linux/include/net/irda/irtty.h	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Sun Feb  7 01:57:33 1999
+ * Modified at:   Mon May 10 13:22:23 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 
@@ -33,8 +33,6 @@
X #include <net/irda/irqueue.h>
X #include <net/irda/irda_device.h>
X 
-#include <net/irda/dongle.h>
-
X #define IRTTY_IOC_MAGIC 'e'
X #define IRTTY_IOCTDONGLE  _IO(IRTTY_IOC_MAGIC, 1)
X #define IRTTY_IOC_MAXNR   1
@@ -43,28 +41,21 @@
X #define N_IRDA         11   /* This one should go in </asm/termio.h> */
X #endif
X 
-struct dongle_q {
-	QUEUE q;
-
-	struct dongle *dongle;
-};
-
X struct irtty_cb {
X 	QUEUE q; /* Must be first */
X 
-/* 	char name[16]; */
-
X 	int	magic;
X 	
X 	struct  tty_struct  *tty;  /* Ptr to TTY structure */
X 	struct  irda_device idev;
-
-	struct dongle_q *dongle_q; /* Has this tty got a dongle attached? */
X };
X  
-int irtty_register_dongle( struct dongle *dongle);
-void irtty_unregister_dongle( struct dongle *dongle);
-
-void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts);
+int irtty_register_dongle(struct dongle *dongle);
+void irtty_unregister_dongle(struct dongle *dongle);
X 
X #endif
+
+
+
+
+
diff -u --recursive --new-file v2.3.3/linux/include/net/irda/toshoboe.h linux/include/net/irda/toshoboe.h
--- v2.3.3/linux/include/net/irda/toshoboe.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/toshoboe.h	Sun May 30 10:27:04 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.3.3/linux/include/net/irda/w83977af_ir.h linux/include/net/irda/w83977af_ir.h
--- v2.3.3/linux/include/net/irda/w83977af_ir.h	Thu Dec 17 09:01:03 1998
+++ linux/include/net/irda/w83977af_ir.h	Sun May 30 10:27:04 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.3.3/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h
--- v2.3.3/linux/include/net/irda/wrapper.h	Sun Mar  7 15:26:44 1999
+++ linux/include/net/irda/wrapper.h	Sun May 30 10:27:04 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 
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 41'
echo 'File patch-2.3.4 is continued in part 42'
echo 42 > _shar_seq_.tmp
#!/bin/sh
# this is part 39 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 39; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
+#define AOFF_task_sas_ss_size	0x00000a20
X #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000a40
+#define ASIZ_task	0x00000a30
X #define AOFF_mm_mmap	0x00000000
X #define ASIZ_mm_mmap	0x00000008
X #define AOFF_mm_mmap_avl	0x00000008
@@ -532,47 +530,45 @@
X #else /* SPIN_LOCK_DEBUG */
X 
@@ -582,177 +578,177 @@
X #define ASIZ_task_wait_chldexit	0x00000030
-#define AOFF_task_vfork_sem	0x00000120
+#define AOFF_task_vfork_sem	0x00000118
X #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000128
+#define AOFF_task_policy	0x00000120
X #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000130
+#define AOFF_task_rt_priority	0x00000128
X #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000138
+#define AOFF_task_it_real_value	0x00000130
X #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000140
+#define AOFF_task_it_prof_value	0x00000138
X #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000148
+#define AOFF_task_it_virt_value	0x00000140
X #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000150
+#define AOFF_task_it_real_incr	0x00000148
X #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000158
+#define AOFF_task_it_prof_incr	0x00000150
X #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000160
+#define AOFF_task_it_virt_incr	0x00000158
X #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000168
+#define AOFF_task_real_timer	0x00000160
X #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000190
+#define AOFF_task_times	0x00000188
X #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x000001b0
+#define AOFF_task_start_time	0x000001a8
X #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x000001b8
+#define AOFF_task_per_cpu_utime	0x000001b0
X #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x000003b8
+#define AOFF_task_min_flt	0x000003b0
X #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000003c0
+#define AOFF_task_maj_flt	0x000003b8
X #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000003c8
+#define AOFF_task_nswap	0x000003c0
X #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000003d0
+#define AOFF_task_cmin_flt	0x000003c8
X #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000003d8
+#define AOFF_task_cmaj_flt	0x000003d0
X #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000003e0
+#define AOFF_task_cnswap	0x000003d8
X #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000003ec
+#define AOFF_task_uid	0x000003e4
X #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000003f0
+#define AOFF_task_euid	0x000003e8
X #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000003f4
+#define AOFF_task_suid	0x000003ec
X #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000003f8
+#define AOFF_task_fsuid	0x000003f0
X #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000003fc
+#define AOFF_task_gid	0x000003f4
X #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x00000400
+#define AOFF_task_egid	0x000003f8
X #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x00000404
+#define AOFF_task_sgid	0x000003fc
X #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x00000408
+#define AOFF_task_fsgid	0x00000400
X #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x0000040c
+#define AOFF_task_ngroups	0x00000404
X #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000410
+#define AOFF_task_groups	0x00000408
X #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000490
+#define AOFF_task_cap_effective	0x00000488
X #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000494
+#define AOFF_task_cap_inheritable	0x0000048c
X #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000498
+#define AOFF_task_cap_permitted	0x00000490
X #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x000004a0
+#define AOFF_task_user	0x00000498
X #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x000004a8
+#define AOFF_task_rlim	0x000004a0
X #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000548
+#define AOFF_task_used_math	0x00000540
X #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x0000054a
+#define AOFF_task_comm	0x00000542
X #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x0000055c
+#define AOFF_task_link_count	0x00000554
X #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000560
+#define AOFF_task_tty	0x00000558
X #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000568
+#define AOFF_task_semundo	0x00000560
X #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000570
+#define AOFF_task_semsleeping	0x00000568
X #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_tss	0x00000580
-#define ASIZ_task_tss	0x00000470
-#define AOFF_task_fs	0x000009f0
+#define AOFF_task_tss	0x00000570
+#define ASIZ_task_tss	0x00000460
+#define AOFF_task_fs	0x000009d0
X #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files 0x000009f8
+#define AOFF_task_files	0x000009d8
X #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm 0x00000a00
+#define AOFF_task_mm	0x000009e0
X #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x00000a08
+#define AOFF_task_sigmask_lock	0x000009e8
X #define ASIZ_task_sigmask_lock	0x0000000c
-#define AOFF_task_sig	0x00000a18
+#define AOFF_task_sig	0x000009f8
X #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x00000a20
+#define AOFF_task_signal	0x00000a00
X #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000a28
+#define AOFF_task_blocked	0x00000a08
X #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000a30
+#define AOFF_task_sigqueue	0x00000a10
X #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000a38
+#define AOFF_task_sigqueue_tail	0x00000a18
X #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000a40
+#define AOFF_task_sas_ss_sp	0x00000a20
X #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000a48
+#define AOFF_task_sas_ss_size	0x00000a28
X #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000a50
+#define ASIZ_task	0x00000a30
X #define AOFF_mm_mmap	0x00000000
X #define ASIZ_mm_mmap	0x00000008
X #define AOFF_mm_mmap_avl	0x00000008
@@ -816,47 +812,45 @@
X #endif /* SPIN_LOCK_DEBUG */
X 
X #endif /* CONFIG_SMP */
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/checksum.h linux/include/asm-sparc64/checksum.h
--- v2.3.3/linux/include/asm-sparc64/checksum.h	Tue Apr 28 22:28:10 1998
+++ linux/include/asm-sparc64/checksum.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.11 1998/04/17 02:37:22 davem Exp $ */
+/* $Id: checksum.h,v 1.12 1999/05/25 16:53:36 jj Exp $ */
X #ifndef __SPARC64_CHECKSUM_H
X #define __SPARC64_CHECKSUM_H
X 
@@ -49,17 +49,20 @@
X csum_partial_copy_nocheck (const char *src, char *dst, int len, 
X 			   unsigned int sum)
X {
-	__asm__ __volatile__ ("wr	%%g0, %0, %%asi" : : "i" (ASI_P));
-	return csum_partial_copy_sparc64(src, dst, len, sum);
+	int ret;
+	unsigned char cur_ds = current->tss.current_ds.seg;
+	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_P));
+	ret = csum_partial_copy_sparc64(src, dst, len, sum);
+	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" (cur_ds));
+	return ret;
X }
X 
X extern __inline__ unsigned int 
X csum_partial_copy_from_user(const char *src, char *dst, int len, 
X 			    unsigned int sum, int *err)
X {
-	__asm__ __volatile__ ("wr	%%g0, %0, %%asi
-			       stx	%1, [%%sp + 0x7ff + 128]
-			      " : : "i" (ASI_S), "r" (err));
+	__asm__ __volatile__ ("stx	%0, [%%sp + 0x7ff + 128]"
+			      : : "r" (err));
X 	return csum_partial_copy_sparc64(src, dst, len, sum);
X }
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/fpumacro.h linux/include/asm-sparc64/fpumacro.h
--- v2.3.3/linux/include/asm-sparc64/fpumacro.h	Tue Aug  4 16:03:35 1998
+++ linux/include/asm-sparc64/fpumacro.h	Thu May 27 09:55:22 1999
@@ -30,44 +30,4 @@
X 	__asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
X }
X 
-extern __inline__ void fpsave(unsigned long *fpregs,
-			      unsigned long *fsr,
-			      unsigned long *gsr)
-{
-	__asm__ __volatile__ ("
-	wr	%%g0, %3, %%asi
-	rd	%%gsr, %%g1
-	membar	#LoadStore | #StoreStore
-	stx	%%fsr, [%1]
-	stx	%%g1, [%2]
-	stda	%%f0, [%0] %%asi
-	stda	%%f16, [%0 + 64] %%asi
-	stda	%%f32, [%0 + 128] %%asi
-	stda	%%f48, [%0 + 192] %%asi
-	membar	#Sync
-"	: /* No outputs */
-	: "r" (fpregs), "r" (fsr), "r" (gsr), "i" (ASI_BLK_P)
-	: "g1");
-}
-
-extern __inline__ void fpload(unsigned long *fpregs,
-			      unsigned long *fsr,
-			      unsigned long *gsr)
-{
-	__asm__ __volatile__ ("
-	wr	%%g0, %3, %%asi
-	membar	#StoreLoad | #LoadLoad
-	ldda	[%0] %%asi, %%f0
-	ldda	[%0 + 64] %%asi, %%f16
-	ldda	[%0 + 128] %%asi, %%f32
-	ldda	[%0 + 192] %%asi, %%f48
-	ldx	[%1], %%fsr
-	ldx	[%2], %%g1
-	wr	%%g1, 0, %%gsr
-	membar	#Sync
-"	: /* No outputs */
-	: "r" (fpregs), "r" (fsr), "r" (gsr), "i" (ASI_BLK_P)
-	: "g1");
-}
-
X #endif /* !(_SPARC64_FPUMACRO_H) */
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/md.h linux/include/asm-sparc64/md.h
--- v2.3.3/linux/include/asm-sparc64/md.h	Mon Jan 12 15:15:58 1998
+++ linux/include/asm-sparc64/md.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: md.h,v 1.2 1997/12/27 16:28:38 jj Exp $
+/* $Id: md.h,v 1.3 1999/05/25 16:53:28 jj Exp $
X  * md.h: High speed xor_block operation for RAID4/5 
X  *            utilizing the UltraSparc Visual Instruction Set.
X  *
@@ -11,7 +11,7 @@
X #include <asm/head.h>
X #include <asm/asi.h>
X 
-#define HAVE_ARCH_XORBLOCK
+#undef HAVE_ARCH_XORBLOCK
X 
X #define MD_XORBLOCK_ALIGNMENT	64
X 
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.3.3/linux/include/asm-sparc64/mmu_context.h	Tue May 11 08:24:32 1999
+++ linux/include/asm-sparc64/mmu_context.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.35 1999/05/08 03:03:20 davem Exp $ */
+/* $Id: mmu_context.h,v 1.36 1999/05/25 16:53:34 jj Exp $ */
X #ifndef __SPARC64_MMU_CONTEXT_H
X #define __SPARC64_MMU_CONTEXT_H
X 
@@ -27,7 +27,7 @@
X #define init_new_context(__mm)	((__mm)->context = NO_CONTEXT)
X 
X /* Kernel threads like rpciod and nfsd drop their mm, and then use
- * init_mm, when this happens we must make sure the tsk->tss.ctx is
+ * init_mm, when this happens we must make sure the secondary context is
X  * updated as well.  Otherwise we have disasters relating to
X  * set_fs/get_fs usage later on.
X  *
@@ -49,12 +49,7 @@
X 	} 									\
X } while (0)
X 
-/* This routine must called with interrupts off,
- * this is necessary to guarentee that the current->tss.ctx
- * to CPU secontary context register relationship is maintained
- * when traps can happen.
- *
- * Also the caller must flush the current set of user windows
+/* The caller must flush the current set of user windows
X  * to the stack (if necessary) before we get here.
X  */
X extern __inline__ void __get_mmu_context(struct task_struct *tsk)
@@ -62,27 +57,30 @@
X 	register unsigned long paddr asm("o5");
X 	register unsigned long pgd_cache asm("o4");
X 	struct mm_struct *mm = tsk->mm;
+	unsigned long asi;
X 
X 	if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD)	&&
X 	   !(tsk->flags & PF_EXITING)) {
X 		unsigned long ctx = tlb_context_cache;
X 		if((mm->context ^ ctx) & CTX_VERSION_MASK)
X 			get_new_mmu_context(mm);
+		tsk->tss.ctx = mm->context & 0x3ff;
+		spitfire_set_secondary_context(mm->context & 0x3ff);
+		__asm__ __volatile__("flush %g6");
X 		if(!(mm->cpu_vm_mask & (1UL<<smp_processor_id()))) {
-			spitfire_set_secondary_context(mm->context & 0x3ff);
-			__asm__ __volatile__("flush %g6");
X 			spitfire_flush_dtlb_secondary_context();
X 			spitfire_flush_itlb_secondary_context();
X 			__asm__ __volatile__("flush %g6");
X 		}
-		/* Don't worry, set_fs() will restore it... */
-		/* Sigh, damned include loops... just poke seg directly.  */
-		tsk->tss.ctx = (tsk->tss.current_ds.seg ?
-				(mm->context & 0x3ff) : 0);
-	} else
+		asi = tsk->tss.current_ds.seg;
+	} else {
X 		tsk->tss.ctx = 0;
-	spitfire_set_secondary_context(tsk->tss.ctx);
-	__asm__ __volatile__("flush %g6");
+		spitfire_set_secondary_context(0);
+		__asm__ __volatile__("flush %g6");
+		asi = ASI_P;
+	}
+	/* Sigh, damned include loops... just poke seg directly.  */
+	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" (asi));
X 	paddr = __pa(mm->pgd);
X 	if((tsk->tss.flags & (SPARC_FLAG_32BIT|SPARC_FLAG_KTHREAD)) ==
X 	   (SPARC_FLAG_32BIT))
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.3.3/linux/include/asm-sparc64/pgtable.h	Sun Mar 28 09:07:47 1999
+++ linux/include/asm-sparc64/pgtable.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.103 1999/03/28 08:40:04 davem Exp $
+/* $Id: pgtable.h,v 1.105 1999/05/27 04:52:51 davem Exp $
X  * pgtable.h: SpitFire page table operations.
X  *
X  * Copyright 1996,1997 David S. Miller (da...@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.3.3/linux/include/asm-sparc64/processor.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/processor.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.53 1999/01/19 07:57:51 davem Exp $
+/* $Id: processor.h,v 1.55 1999/05/27 04:52:54 davem Exp $
X  * include/asm-sparc64/processor.h
X  *
X  * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu)
@@ -7,6 +7,12 @@
X #ifndef __ASM_SPARC64_PROCESSOR_H
X #define __ASM_SPARC64_PROCESSOR_H
X 
+/*
+ * Sparc64 implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
+
X #include <asm/asi.h>
X #include <asm/a.out.h>
X #include <asm/pstate.h>
@@ -36,7 +42,7 @@
X #define NSWINS		7
X 
X typedef struct {
-	unsigned long seg;
+	unsigned char seg;
X } mm_segment_t;
X 
X /* The Sparc processor specific thread struct. */
@@ -45,15 +51,19 @@
X 	unsigned short wstate;
X 	unsigned short cwp;
X 	unsigned short flags;
-	unsigned short ctx;
+	mm_segment_t current_ds;
X 
X /*DC2*/	unsigned short w_saved;
X 	unsigned short new_signal;
-	unsigned int ___pad;
-	mm_segment_t current_ds;
+	unsigned short ctx;
+	struct pt_regs *kregs;
X 
-/*DC3*/	struct pt_regs *kregs;
-	unsigned long *utraps;
+/*DC3*/ unsigned long *utraps;
+	unsigned char fpdepth;
+	unsigned char fpsaved[7];
+	
+/*DC4*/	unsigned char gsr[7];
+	unsigned long xfsr[7];
X 
X 	struct reg_window reg_window[NSWINS] __attribute__ ((aligned (16)));
X 	unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));
@@ -66,10 +76,6 @@
X 	u64 kernel_cntd0, kernel_cntd1;
X 	u64 pcr_reg;
X 
-	unsigned char fpdepth;
-	unsigned char fpsaved[7];
-	unsigned char gsr[7];
-	unsigned long xfsr[7];
X };
X 
X #endif /* !(__ASSEMBLY__) */
@@ -85,12 +91,14 @@
X 		    NULL, PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
X 
X #define INIT_TSS  {						\
-/* ksp, wstate, cwp, flags,              ctx, */ 		\
-   0,   0,      0,   SPARC_FLAG_KTHREAD, 0,			\
-/* w_saved, new_signal, padding, current_ds, */			\
-   0,       0,          0,       KERNEL_DS,			\
-/* kregs,   utraps, */						\
-   0,       0,							\
+/* ksp, wstate, cwp, flags,              current_ds, */ 	\
+   0,   0,      0,   SPARC_FLAG_KTHREAD, KERNEL_DS,		\
+/* w_saved, new_signal, ctx,		 kregs, */		\
+   0,       0,          0,		 0,			\
+/* utraps, */							\
+   0,								\
+/* fpdepth, fpsaved, gsr,   xfsr */				\
+   0,       { 0 },   { 0 }, { 0 },				\
X /* reg_window */						\
X    { { { 0, }, { 0, } }, }, 					\
X /* rwbuf_stkptrs */						\
@@ -99,8 +107,6 @@
X    0,           0,						\
X /* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \
X    0,          0,          0,		 0,            0,	\
-/* fpdepth, fpsaved, gsr,   xfsr */				\
-   0,       { 0 },   { 0 }, { 0 },				\
X }
X 
X #ifndef __ASSEMBLY__
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/softirq.h linux/include/asm-sparc64/softirq.h
--- v2.3.3/linux/include/asm-sparc64/softirq.h	Tue Mar 16 21:52:06 1999
+++ linux/include/asm-sparc64/softirq.h	Mon May 31 22:08:10 1999
@@ -16,6 +16,9 @@
X #define local_bh_count		(cpu_data[smp_processor_id()].bh_count)
X #endif
X 
+#define local_bh_disable()	(local_bh_count++)
+#define local_bh_enable()	(local_bh_count--)
+
X /* The locking mechanism for base handlers, to prevent re-entrancy,
X  * is entirely private to an implementation, it should not be
X  * referenced at all outside of this file.
@@ -94,7 +97,8 @@
X static inline int softirq_trylock(int cpu)
X {
X 	if (spin_trylock(&global_bh_count)) {
-		if (atomic_read(&global_bh_lock) == 0) {
+		if (atomic_read(&global_bh_lock) == 0 &&
+		    cpu_data[cpu].bh_count == 0) {
X 			++(cpu_data[cpu].bh_count);
X 			return 1;
X 		}
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h
--- v2.3.3/linux/include/asm-sparc64/spinlock.h	Fri May 14 18:55:29 1999
+++ linux/include/asm-sparc64/spinlock.h	Tue May 25 13:06:34 1999
@@ -20,6 +20,14 @@
X #define spin_unlock(lock)	do { } while(0)
X #define spin_lock_irq(lock)	cli()
X #define spin_unlock_irq(lock)	sti()
+#define spin_lock_bh(lock) \
+do {	local_bh_count++; \
+	barrier(); \
+} while(0)
+#define spin_unlock_bh(lock) \
+do {	barrier(); \
+	local_bh_count--; \
+} while(0)
X 
X #define spin_lock_irqsave(lock, flags)		save_and_cli(flags)
X #define spin_unlock_irqrestore(lock, flags)	restore_flags(flags)
@@ -43,9 +51,28 @@
X #define write_unlock(lock)	do { } while(0)
X #define read_lock_irq(lock)	cli()
X #define read_unlock_irq(lock)	sti()
+#define read_lock_bh(lock) \
+do {	local_bh_count++; \
+	barrier(); \
+} while(0)
+#define read_unlock_bh(lock) \
+do {	barrier(); \
+	local_bh_count--; \
+} while(0)
+
X #define write_lock_irq(lock)	cli()
X #define write_unlock_irq(lock)	sti()
X 
+#define write_lock_bh(lock) \
+do {	local_bh_count++; \
+	barrier(); \
+} while(0)
+ 
+#define write_unlock_bh(lock) \
+do {	barrier(); \
+	local_bh_count--; \
+} while(0)
+
X #define read_lock_irqsave(lock, flags)		save_and_cli(flags)
X #define read_unlock_irqrestore(lock, flags)	restore_flags(flags)
X #define write_lock_irqsave(lock, flags)		save_and_cli(flags)
@@ -149,6 +176,16 @@
X 	: "memory");
X }
X 
+#define spin_lock_bh(__lock)	\
+do {	local_bh_count++;	\
+	spin_lock(__lock);	\
+} while(0)
+
+#define spin_unlock_bh(__lock)		\
+do {	spin_unlock(__lock);		\
+	local_bh_count--;		\
+} while(0)
+
X #define spin_lock_irqsave(__lock, flags)			\
X do {	register spinlock_t *__lp asm("g1");			\
X 	__lp = (__lock);					\
@@ -205,9 +242,11 @@
X #define spin_trylock(lp)	_spin_trylock(lp)
X #define spin_lock(lock)		_do_spin_lock(lock, "spin_lock")
X #define spin_lock_irq(lock)	do { __cli(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
+#define spin_lock_bh(lock) do { local_bh_count++; _do_spin_lock(lock, "spin_lock_bh"); } while(0)
X #define spin_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_spin_lock(lock, "spin_lock_irqsave"); } while(0)
X #define spin_unlock(lock)	_do_spin_unlock(lock)
X #define spin_unlock_irq(lock)	do { _do_spin_unlock(lock); __sti(); } while(0)
+#define spin_unlock_bh(lock) do { _do_spin_unlock(lock); local_bh_count--; } while(0)
X #define spin_unlock_irqrestore(lock, flags) do { _do_spin_unlock(lock); __restore_flags(flags); } while(0)
X 
X #endif /* SPIN_LOCK_DEBUG */
@@ -303,8 +342,12 @@
X 
X #define read_lock_irq(lock)	do { __cli(); read_lock(lock); } while (0)
X #define read_unlock_irq(lock)	do { read_unlock(lock); __sti(); } while (0)
+#define read_lock_bh(lock)	do { local_bh_count++; read_lock(lock); } while (0)
+#define read_unlock_bh(lock)	do { read_unlock(lock); local_bh_count--; } while (0)
X #define write_lock_irq(lock)	do { __cli(); write_lock(lock); } while (0)
X #define write_unlock_irq(lock)	do { write_unlock(lock); __sti(); } while (0)
+#define write_lock_bh(lock)	do { local_bh_count++; write_lock(lock); } while (0)
+#define write_unlock_bh(lock)	do { write_unlock(lock); local_bh_count--; } while (0)
X 
X #define read_lock_irqsave(lock, flags)	\
X 	do { __save_and_cli(flags); read_lock(lock); } while (0)
@@ -336,6 +379,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define read_lock_irq(lock)	do { __cli(); _do_read_lock(lock, "read_lock_irq"); } while(0)
+#define read_lock_bh(lock) do { local_bh_count++; _do_read_lock(lock, "read_lock_bh"); } while(0)
X #define read_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_read_lock(lock, "read_lock_irqsave"); } while(0)
X 
X #define read_unlock(lock) \
@@ -345,6 +389,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define read_unlock_irq(lock)	do { _do_read_unlock(lock, "read_unlock_irq"); __sti() } while(0)
+#define read_unlock_bh(lock) do { _do_read_unlock(lock, "read_unlock_bh"); local_bh_count--; } while(0)
X #define read_unlock_irqrestore(lock, flags) do { _do_read_unlock(lock, "read_unlock_irqrestore"); __restore_flags(flags); } while(0)
X 
X #define write_lock(lock) \
@@ -354,6 +399,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define write_lock_irq(lock)	do { __cli(); _do_write_lock(lock, "write_lock_irq"); } while(0)
+#define write_lock_bh(lock) do { local_bh_count++; _do_write_lock(lock, "write_lock_bh"); } while(0)
X #define write_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_write_lock(lock, "write_lock_irqsave"); } while(0)
X 
X #define write_unlock(lock) \
@@ -363,6 +409,7 @@
X 	__restore_flags(flags); \
X } while(0)
X #define write_unlock_irq(lock)	do { _do_write_unlock(lock); __sti(); } while(0)
+#define write_unlock_bh(lock) do { _do_write_unlock(lock); local_bh_count--; } while(0)
X #define write_unlock_irqrestore(lock, flags) do { _do_write_unlock(lock); __restore_flags(flags); } while(0)
X 
X #endif /* SPIN_LOCK_DEBUG */
diff -u --recursive --new-file v2.3.3/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.3.3/linux/include/asm-sparc64/uaccess.h	Tue May 11 08:24:32 1999
+++ linux/include/asm-sparc64/uaccess.h	Thu May 27 09:55:22 1999
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.29 1999/05/08 03:03:25 davem Exp $ */
+/* $Id: uaccess.h,v 1.30 1999/05/25 16:53:32 jj Exp $ */
X #ifndef _ASM_UACCESS_H
X #define _ASM_UACCESS_H
X 
@@ -30,8 +30,8 @@
X  * "For historical reasons, these macros are grossly misnamed." -Linus
X  */
X 
-#define KERNEL_DS   ((mm_segment_t) { 0x00 })
-#define USER_DS     ((mm_segment_t) { 0x2B })	/* har har har */
+#define KERNEL_DS   ((mm_segment_t) { ASI_P })
+#define USER_DS     ((mm_segment_t) { ASI_AIUS })	/* har har har */
X 
X #define VERIFY_READ	0
X #define VERIFY_WRITE	1
@@ -43,17 +43,8 @@
X 
X #define set_fs(val)								\
X do {										\
-	if (current->tss.current_ds.seg != val.seg) {				\
-		current->tss.current_ds = (val);				\
-		if (segment_eq((val), KERNEL_DS)) {				\
-			flushw_user ();						\
-			current->tss.ctx = 0;					\
-		} else {							\
-			current->tss.ctx = (current->mm->context & 0x3ff);	\
-		}								\
-		spitfire_set_secondary_context(current->tss.ctx); 		\
-		__asm__ __volatile__("flush %g6");				\
-	}									\
+	current->tss.current_ds = (val);					\
+	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));	\
X } while(0)
X 
X #define __user_ok(addr,size) 1
@@ -154,7 +145,7 @@
X #define __put_user_asm(x,size,addr,ret)					\
X __asm__ __volatile__(							\
X 	"/* Put user asm, inline. */\n"					\
-"1:\t"	"st"#size "a %1, [%2] %4\n\t"					\
+"1:\t"	"st"#size "a %1, [%2] %%asi\n\t"				\
X 	"clr	%0\n"							\
X "2:\n\n\t"								\
X 	".section .fixup,#alloc,#execinstr\n\t"				\
@@ -168,22 +159,22 @@
X 	".word	1b, 3b\n\t"						\
X 	".previous\n\n\t"						\
X        : "=r" (ret) : "r" (x), "r" (__m(addr)),				\
-	 "i" (-EFAULT), "i" (ASI_S))
+	 "i" (-EFAULT))
X 
X #define __put_user_asm_ret(x,size,addr,ret,foo)				\
X if (__builtin_constant_p(ret) && ret == -EFAULT)			\
X __asm__ __volatile__(							\
X 	"/* Put user asm ret, inline. */\n"				\
-"1:\t"	"st"#size "a %1, [%2] %3\n\n\t"					\
+"1:\t"	"st"#size "a %1, [%2] %%asi\n\n\t"				\
X 	".section __ex_table,#alloc\n\t"				\
X 	".align	4\n\t"							\
X 	".word	1b, __ret_efault\n\n\t"					\
X 	".previous\n\n\t"						\
-       : "=r" (foo) : "r" (x), "r" (__m(addr)), "i" (ASI_S));		\
+       : "=r" (foo) : "r" (x), "r" (__m(addr)));			\
X else									\
X __asm__ __volatile(							\
X 	"/* Put user asm ret, inline. */\n"				\
-"1:\t"	"st"#size "a %1, [%2] %4\n\n\t"					\
+"1:\t"	"st"#size "a %1, [%2] %%asi\n\n\t"				\
X 	".section .fixup,#alloc,#execinstr\n\t"				\
X 	".align	4\n"							\
X "3:\n\t"								\
@@ -195,7 +186,7 @@
X 	".word	1b, 3b\n\n\t"						\
X 	".previous\n\n\t"						\
X        : "=r" (foo) : "r" (x), "r" (__m(addr)),				\
-         "i" (ret), "i" (ASI_S))
+         "i" (ret))
X 
X extern int __put_user_bad(void);
X 
@@ -223,7 +214,7 @@
X #define __get_user_asm(x,size,addr,ret)					\
X __asm__ __volatile__(							\
X 	"/* Get user asm, inline. */\n"					\
-"1:\t"	"ld"#size "a [%2] %4, %1\n\t"					\
+"1:\t"	"ld"#size "a [%2] %%asi, %1\n\t"				\
X 	"clr	%0\n"							\
X "2:\n\n\t"								\
X 	".section .fixup,#alloc,#execinstr\n\t"				\
@@ -238,33 +229,33 @@
X 	".word	1b, 3b\n\n\t"						\
X 	".previous\n\t"							\
X        : "=r" (ret), "=r" (x) : "r" (__m(addr)),			\
-	 "i" (-EFAULT), "i" (ASI_S))
+	 "i" (-EFAULT))
X 
X #define __get_user_asm_ret(x,size,addr,retval)				\
X if (__builtin_constant_p(retval) && retval == -EFAULT)			\
X __asm__ __volatile__(							\
X 	"/* Get user asm ret, inline. */\n"				\
-"1:\t"	"ld"#size "a [%1] %2, %0\n\n\t"					\
+"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"				\
X 	".section __ex_table,#alloc\n\t"				\
X 	".align	4\n\t"							\
X 	".word	1b,__ret_efault\n\n\t"					\
X 	".previous\n\t"							\
-       : "=r" (x) : "r" (__m(addr)), "i" (ASI_S));			\
+       : "=r" (x) : "r" (__m(addr)));					\
X else									\
X __asm__ __volatile__(							\
X 	"/* Get user asm ret, inline. */\n"				\
-"1:\t"	"ld"#size "a [%1] %2, %0\n\n\t"					\
+"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"				\
X 	".section .fixup,#alloc,#execinstr\n\t"				\
X 	".align	4\n"							\
X "3:\n\t"								\
X 	"ret\n\t"							\
-	" restore %%g0, %3, %%o0\n\n\t"					\
+	" restore %%g0, %2, %%o0\n\n\t"					\
X 	".previous\n\t"							\
X 	".section __ex_table,#alloc\n\t"				\
X 	".align	4\n\t"							\
X 	".word	1b, 3b\n\n\t"						\
X 	".previous\n\t"							\
-       : "=r" (x) : "r" (__m(addr)), "i" (retval), "i" (ASI_S))
+       : "=r" (x) : "r" (__m(addr)), "i" (retval))
X 
X extern int __get_user_bad(void);
X 
@@ -339,8 +330,6 @@
X {
X 	extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size);
X 	
-	
-	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_S));
X 	return __bzero_noasi(addr, size);
X }
X 
diff -u --recursive --new-file v2.3.3/linux/include/linux/b1lli.h linux/include/linux/b1lli.h
--- v2.3.3/linux/include/linux/b1lli.h	Wed Apr  1 16:20:56 1998
+++ linux/include/linux/b1lli.h	Sun May 23 10:03:42 1999
@@ -1,11 +1,33 @@
X /*
- * $Id: b1lli.h,v 1.3 1998/01/31 10:54:37 calle Exp $
+ * $Id: b1lli.h,v 1.6 1999/04/15 19:49:36 calle Exp $
X  *
X  * ISDN lowlevel-module for AVM B1-card.
X  *
X  * Copyright 1996 by Carsten Paeth (ca...@calle.in-berlin.de)
X  *
X  * $Log: b1lli.h,v $
+ * Revision 1.6  1999/04/15 19:49:36  calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.5  1998/10/25 14:50:28  fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.4  1998/03/29 16:05:02  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.9  1998/03/20 14:30:02  calle
+ * added cardnr to detect if you try to add same T1 to different io address.
+ * change number of nccis depending on number of channels.
+ *
+ * Revision 1.1.2.8  1998/03/04 17:32:33  calle
+ * Changes for T1.
+ *
+ * Revision 1.1.2.7  1998/02/27 15:38:29  calle
+ * T1 running with slow link.
+ *
+ * Revision 1.1.2.6  1998/02/24 17:57:36  calle
+ * changes for T1.
+ *
X  * Revision 1.3  1998/01/31 10:54:37  calle
X  * include changes for PCMCIA cards from 2.0 version
X  *
@@ -70,15 +92,17 @@
X 	int irq;
X } avmb1_carddef;
X 
-#define AVM_CARDTYPE_B1	0
-#define AVM_CARDTYPE_T1	1
-#define AVM_CARDTYPE_M1	2
-#define AVM_CARDTYPE_M2	3
+#define AVM_CARDTYPE_B1		0
+#define AVM_CARDTYPE_T1		1
+#define AVM_CARDTYPE_M1		2
+#define AVM_CARDTYPE_M2		3
+#define AVM_CARDTYPE_B1PCI	4
X 
X typedef struct avmb1_extcarddef {
X 	int port;
X 	int irq;
X         int cardtype;
+        int cardnr;  /* for HEMA/T1 */
X } avmb1_extcarddef;
X 
X #define	AVMB1_LOAD		0	/* load image to card */
@@ -87,6 +111,7 @@
X #define	AVMB1_LOAD_AND_CONFIG	3	/* load image and config to card */
X #define	AVMB1_ADDCARD_WITH_TYPE	4	/* add a new card, with cardtype */
X #define AVMB1_GET_CARDINFO	5	/* get cardtype */
+#define AVMB1_REMOVECARD	6	/* remove a card (usefull for T1) */
X 
X 
X 
@@ -103,14 +128,12 @@
X 
X #ifdef __KERNEL__
X 
-#define	AVMB1_PORTLEN	0x1f
+#define	AVMB1_PORTLEN		0x1f
X 
-#define AVM_MAXVERSION	8
-#define AVM_NBCHAN	2
+#define AVM_MAXVERSION		8
X 
-#define AVM_NAPPS	30
-#define AVM_NPLCI	5
-#define AVM_NNCCI	6
+#define AVM_NAPPS		30
+#define AVM_NNCCI_PER_CHANNEL	4
X 
X /*
X  * Main driver data
@@ -119,9 +142,10 @@
X typedef struct avmb1_card {
X 	struct avmb1_card *next;
X 	int cnr;
-	unsigned short port;
+	unsigned int port;
X 	unsigned irq;
X 	int cardtype;
+	int cardnr; /* for T1-HEMA */
X 	volatile unsigned short cardstate;
X 	int interrupt;
X 	int blocked;
@@ -149,23 +173,26 @@
X 
X 
X /* b1lli.c */
-int B1_detect(unsigned short base, int cardtype);
-void B1_reset(unsigned short base);
-int B1_load_t4file(unsigned short base, avmb1_t4file * t4file);
-int B1_load_config(unsigned short base, avmb1_t4file * config);
-int B1_loaded(unsigned short base);
-unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype);
-unsigned char B1_enable_irq(unsigned short base);
-unsigned char B1_disable_irq(unsigned short base);
+int B1_detect(unsigned int base, int cardtype);
+int T1_detectandinit(unsigned int base, unsigned irq, int cardnr);
+void B1_reset(unsigned int base);
+void T1_reset(unsigned int base);
+int B1_load_t4file(unsigned int base, avmb1_t4file * t4file);
+int B1_load_config(unsigned int base, avmb1_t4file * config);
+int B1_loaded(unsigned int base);
+void B1_setinterrupt(unsigned int base, unsigned irq, int cardtype);
+unsigned char B1_disable_irq(unsigned int base);
+void T1_disable_irq(unsigned int base);
X int B1_valid_irq(unsigned irq, int cardtype);
+int B1_valid_port(unsigned port, int cardtype);
X void B1_handle_interrupt(avmb1_card * card);
-void B1_send_init(unsigned short port,
+void B1_send_init(unsigned int port,
X unsigned int napps, unsigned int nncci, unsigned int cardnr);
-void B1_send_register(unsigned short port,
+void B1_send_register(unsigned int port,
X 		      __u16 appid, __u32 nmsg,
X 		      __u32 nb3conn, __u32 nb3blocks, __u32 b3bsize);
-void B1_send_release(unsigned short port, __u16 appid);
-void B1_send_message(unsigned short port, struct sk_buff *skb);
+void B1_send_release(unsigned int port, __u16 appid);
+void B1_send_message(unsigned int port, struct sk_buff *skb);
X 
X /* b1capi.c */
X void avmb1_handle_new_ncci(avmb1_card * card,
diff -u --recursive --new-file v2.3.3/linux/include/linux/blkpg.h linux/include/linux/blkpg.h
--- v2.3.3/linux/include/linux/blkpg.h	Mon May 17 09:55:23 1999
+++ linux/include/linux/blkpg.h	Sat May 22 13:38:37 1999
@@ -34,7 +34,7 @@
X         int flags;
X         int datalen;
X         void *data;
-} *p;
+};
X 
X /* The subfunctions (for the op field) */
X #define BLKPG_ADD_PARTITION	1
diff -u --recursive --new-file v2.3.3/linux/include/linux/cyclades.h linux/include/linux/cyclades.h
--- v2.3.3/linux/include/linux/cyclades.h	Fri May 14 18:55:29 1999
+++ linux/include/linux/cyclades.h	Mon May 24 22:38:07 1999
@@ -557,7 +557,8 @@
X 	unsigned long		event;
X 	unsigned long		last_active;
X 	int			count;	/* # of fd on device */
-	int                     x_break;
+	int                     breakon;
+	int                     breakoff;
X 	int			blocked_open; /* # of blocked opens */
X 	long			session; /* Session of opening process */
X 	long			pgrp; /* pgrp of opening process */
diff -u --recursive --new-file v2.3.3/linux/include/linux/dn.h linux/include/linux/dn.h
--- v2.3.3/linux/include/linux/dn.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/dn.h	Wed May 26 09:37:03 1999
@@ -0,0 +1,161 @@
+#ifndef _LINUX_DN_H
+#define _LINUX_DN_H
+
+/*
+
+	DECnet Data Structures and Constants
+
+*/
+
+/* 
+ * DNPROTO_NSP can't be the same as SOL_SOCKET, 
+ * so increment each by one (compared to ULTRIX)
+ */
+#define DNPROTO_NSP     2                       /* NSP protocol number       */
+#define DNPROTO_ROU     3                       /* Routing protocol number   */
+#define DNPROTO_NML     4                       /* Net mgt protocol number   */
+#define DNPROTO_EVL     5                       /* Evl protocol number (usr) */
+#define DNPROTO_EVR     6                       /* Evl protocol number (evl) */
+#define DNPROTO_NSPT    7                       /* NSP trace protocol number */
+
+
+#define DN_ADDL		2
+#define DN_MAXADDL	2 /* ULTRIX headers have 20 here, but pathworks has 2 */
+#define DN_MAXOPTL	16
+#define DN_MAXOBJL	16
+#define DN_MAXACCL	40
+#define DN_MAXALIASL	128
+#define DN_MAXNODEL	256
+#define DNBUFSIZE	65023
+
+/* 
+ * SET/GET Socket options  - must match the DSO_ numbers below
+ */
+#define SO_CONDATA      1
+#define SO_CONACCESS    2
+#define SO_PROXYUSR     3
+#define SO_LINKINFO     7
+
+#define DSO_CONDATA     1        /* Set/Get connect data                */
+#define DSO_DISDATA     10       /* Set/Get disconnect data             */
+#define DSO_CONACCESS   2        /* Set/Get connect access data         */
+#define DSO_ACCEPTMODE  4        /* Set/Get accept mode                 */
+#define DSO_CONACCEPT   5        /* Accept deferred connection          */
+#define DSO_CONREJECT   6        /* Reject deferred connection          */
+#define DSO_LINKINFO    7        /* Set/Get link information            */
+#define DSO_STREAM      8        /* Set socket type to stream           */
+#define DSO_SEQPACKET   9        /* Set socket type to sequenced packet */
+#define DSO_MAX         10       /* Maximum option number               */
+
+
+/* LINK States */
+#define LL_INACTIVE	0
+#define LL_CONNECTING	1
+#define LL_RUNNING	2
+#define LL_DISCONNECTING 3
+
+#define ACC_IMMED 0
+#define ACC_DEFER 1
+
+#define SDF_WILD        1                  /* Wild card object          */
+#define SDF_PROXY       2                  /* Addr eligible for proxy   */
+#define SDF_UICPROXY    4                  /* Use uic-based proxy       */
+
+/* Structures */
+
+
+struct dn_naddr 
+{
+	unsigned short		a_len;
+	unsigned char a_addr[DN_MAXADDL];
+};
+
+struct sockaddr_dn
+{
+	unsigned short		sdn_family;
+	unsigned char		sdn_flags;
+	unsigned char		sdn_objnum;
+	unsigned short		sdn_objnamel;
+	unsigned char		sdn_objname[DN_MAXOBJL];
+	struct   dn_naddr	sdn_add;
+};
+#define sdn_nodeaddrl   sdn_add.a_len   /* Node address length  */
+#define sdn_nodeaddr    sdn_add.a_addr  /* Node address         */
+
+
+
+/*
+ * DECnet set/get DSO_CONDATA, DSO_DISDATA (optional data) structure
+ */
+struct optdata_dn {
+        unsigned short  opt_status;     /* Extended status return */
+#define opt_sts opt_status
+        unsigned short  opt_optl;       /* Length of user data    */
+        unsigned char   opt_data[16];   /* User data              */
+};
+
+struct accessdata_dn
+{
+	unsigned char		acc_accl;
+	unsigned char		acc_acc[DN_MAXACCL];
+	unsigned char 		acc_passl;
+	unsigned char		acc_pass[DN_MAXACCL];
+	unsigned char 		acc_userl;
+	unsigned char		acc_user[DN_MAXACCL];
+};
+
+/*
+ * DECnet logical link information structure
+ */
+struct linkinfo_dn {
+        unsigned short  idn_segsize;    /* Segment size for link */
+        unsigned char   idn_linkstate;  /* Logical link state    */
+};
+
+/*
+ * Ethernet address format (for DECnet)
+ */
+union etheraddress {
+        unsigned char dne_addr[6];             /* Full ethernet address */
+  struct {
+                unsigned char dne_hiord[4];    /* DECnet HIORD prefix   */
+                unsigned char dne_nodeaddr[2]; /* DECnet node address   */
+  } dne_remote;
+};
+
+
+/*
+ * DECnet physical socket address format
+ */
+struct dn_addr {
+        unsigned short dna_family;      /* AF_DECnet               */
+        union etheraddress dna_netaddr; /* DECnet ethernet address */
+};
+
+#define DECNET_IOCTL_BASE 0x89 /* PROTOPRIVATE range */
+
+#define SIOCSNETADDR  _IOW(DECNET_IOCTL_BASE, 0xe0, struct dn_naddr)
+#define SIOCGNETADDR  _IOR(DECNET_IOCTL_BASE, 0xe1, struct dn_naddr)
+#define OSIOCSNETADDR _IOW(DECNET_IOCTL_BASE, 0xe0, int)
+#define OSIOCGNETADDR _IOR(DECNET_IOCTL_BASE, 0xe1, int)
+
+/*
+ * An unofficial structure used to set/get routes.
+ * Be warned, this will probably change as the routing
+ * evolves. Also this is only for use with the ioctl()
+ * and the routing will use rtnetlink eventually.
+ */
+struct dn_fib_rtinfo {
+	unsigned long flags; /* Flags */
+#define DN_FIB_RTINFO_F_REPLACE 0x0001  /* Replace any existing route */
+#define DN_FIB_RTINFO_F_DEVCOST 0x0002  /* Add cost of device         */
+	unsigned long timeout; /* Time in seconds route should last */
+	unsigned short src;  /* Source Address, 0 = any */
+	unsigned short dst;  /* Destination Address     */
+	unsigned short nhp;  /* Next Hop Address        */
+	unsigned short hops; /* Hops on path            */
+	unsigned short cost; /* Cost of path            */
+	char device[16];
+};
+
+#endif /* _LINUX_DN_H */
diff -u --recursive --new-file v2.3.3/linux/include/linux/i2c.h linux/include/linux/i2c.h
--- v2.3.3/linux/include/linux/i2c.h	Fri Jan 15 14:36:21 1999
+++ linux/include/linux/i2c.h	Tue May 25 13:57:55 1999
@@ -22,6 +22,8 @@
X  *
X  */
X 
+#include <linux/version.h>
+
X #define I2C_BUS_MAX       4    /* max # of bus drivers  */
X #define I2C_DRIVER_MAX    8    /* max # of chip drivers */
X #define I2C_DEVICE_MAX    8    /* max # if devices per bus/driver */
@@ -35,6 +37,7 @@
X #define I2C_DRIVERID_VIDEOTEXT	 3
X 
X #define I2C_BUSID_BT848		1	/* I2C bus on a BT848 */
+#define I2C_BUSID_PARPORT	2	/* Bit banging on a parallel port */
X 
X /*
X  * struct for a driver for a i2c chip (tuner, soundprocessor,
diff -u --recursive --new-file v2.3.3/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.3.3/linux/include/linux/ide.h	Fri May 14 18:55:29 1999
+++ linux/include/linux/ide.h	Fri May 28 09:34:41 1999
@@ -810,12 +810,4 @@
X unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
X #endif
X 
-/* This is too ugly to live! */
-#ifdef CONFIG_BLK_DEV_PDC4030
-#include "pdc4030.h"
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
-#else
-#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
X #endif /* _IDE_H */
diff -u --recursive --new-file v2.3.3/linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- v2.3.3/linux/include/linux/if_arp.h	Tue May 11 13:05:12 1999
+++ linux/include/linux/if_arp.h	Wed May 26 09:37:03 1999
@@ -49,6 +49,7 @@
X #define ARPHRD_PPP	512
X #define ARPHRD_HDLC	513		/* (Cisco) HDLC 		*/
X #define ARPHRD_LAPB	516		/* LAPB				*/
+#define ARPHRD_DDCMP    517		/* Digital's DDCMP protocol     */
X 
X #define ARPHRD_TUNNEL	768		/* IPIP tunnel			*/
X #define ARPHRD_TUNNEL6	769		/* IPIP6 tunnel			*/
diff -u --recursive --new-file v2.3.3/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.3.3/linux/include/linux/interrupt.h	Tue May 11 13:04:00 1999
+++ linux/include/linux/interrupt.h	Mon May 31 22:08:10 1999
@@ -35,6 +35,7 @@
X 	SERIAL_BH,
X 	RISCOM8_BH,
X 	SPECIALIX_BH,
+	AURORA_BH,
X 	ESP_BH,
X 	NET_BH,
X 	SCSI_BH,
diff -u --recursive --new-file v2.3.3/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.3.3/linux/include/linux/isdn.h	Fri May 14 18:55:29 1999
+++ linux/include/linux/isdn.h	Sun May 23 10:03:42 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.37 1998/02/22 19:45:24 fritz Exp $
+/* $Id: isdn.h,v 1.64 1999/04/18 14:57:14 fritz Exp $
X  *
X  * Main header for the Linux ISDN subsystem (linklevel).
X  *
@@ -20,11 +20,102 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
X  * $Log: isdn.h,v $
+ * Revision 1.64  1999/04/18 14:57:14  fritz
+ * Removed TIMRU stuff
+ *
+ * Revision 1.63  1999/04/18 14:07:18  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.62  1999/04/12 13:16:54  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.61  1999/03/02 11:43:21  armin
+ * Added variable to store connect-message of Modem.
+ * Added Timer-define for RegS7 (Wait for Carrier).
+ *
+ * Revision 1.60  1998/10/25 14:50:29  fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.59  1998/10/23 10:18:55  paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.58  1998/10/23 10:10:06  fritz
+ * Test-Checkin
+ *
+ * Revision 1.57  1998/08/31 21:10:01  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
+ * Revision 1.56  1998/07/26 18:46:52  armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.55  1998/06/26 15:13:17  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.54  1998/06/18 23:32:01  fritz
+ * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
+ * Removed direct-senddown feature in isdn_tty_write because it will
+ * never succeed with locking and is useless anyway.
+ *
+ * Revision 1.53  1998/06/17 19:51:51  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.52  1998/06/12 11:42:18  detabc
+ * cleanup abc
+ *
+ * Revision 1.51  1998/06/02 12:10:30  detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.50  1998/05/05 23:11:51  detabc
+ * add Item to stop icmp-unreach (max. 6 times of dialwait delay)
+ *
+ * Revision 1.49  1998/05/03 17:45:00  detabc
+ * Add Item to send icmp-host-unreach to all packets
+ *
+ * Revision 1.48  1998/04/26 19:58:14  detabc
+ * include the new abc-extension-items from 2.0.xx kernels
+ * remove some unused code
+ *
+ * Revision 1.47  1998/04/21 18:00:25  detabc
+ * Add items for secure-callback (abc-extension only)
+ *
+ * Revision 1.46  1998/04/14 16:28:59  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.45  1998/03/24 16:33:12  hipp
+ * More CCP changes. BSD compression now "works" on a local loopback link.
+ * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
+ *
+ * Revision 1.44  1998/03/22 18:50:56  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.43  1998/03/09 17:46:44  he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.42  1998/03/08 13:53:46  detabc
+ * add ABC-variables in structur isdn_devt
+ *
+ * Revision 1.41  1998/03/08 13:14:37  detabc
+ * abc-extension support for kernels > 2.1.x
+ * first try (sorry experimental)
+ *
+ * Revision 1.40  1998/03/08 01:08:29  fritz
+ * Increased NET_DV because of TIMRU
+ *
+ * Revision 1.39  1998/03/07 22:42:49  fritz
+ * Starting generic module support (Nothing usable yet).
+ *
+ * Revision 1.38  1998/03/07 18:21:29  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
X  * Revision 1.37  1998/02/22 19:45:24  fritz
X  * Some changes regarding V.110
X  *
@@ -163,6 +254,7 @@
X #ifndef isdn_h
X #define isdn_h
X 
+#include <linux/config.h>
X #include <linux/ioctl.h>
X 
X #define ISDN_TTY_MAJOR    43
@@ -174,14 +266,20 @@
X  * the correspondent code in isdn.c
X  */
X 
+#ifdef CONFIG_COBALT_MICRO_SERVER
+/* Save memory */
+#define ISDN_MAX_DRIVERS    2
+#define ISDN_MAX_CHANNELS   8
+#else
X #define ISDN_MAX_DRIVERS    32
X #define ISDN_MAX_CHANNELS   64
+#endif
X #define ISDN_MINOR_B        0
X #define ISDN_MINOR_BMAX     (ISDN_MAX_CHANNELS-1)
-#define ISDN_MINOR_CTRL     ISDN_MAX_CHANNELS
-#define ISDN_MINOR_CTRLMAX  (2*ISDN_MAX_CHANNELS-1)
-#define ISDN_MINOR_PPP      (2*ISDN_MAX_CHANNELS)
-#define ISDN_MINOR_PPPMAX   (3*ISDN_MAX_CHANNELS-1)
+#define ISDN_MINOR_CTRL     64
+#define ISDN_MINOR_CTRLMAX  (64 + (ISDN_MAX_CHANNELS-1))
+#define ISDN_MINOR_PPP      128
+#define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
X #define ISDN_MINOR_STATUS   255
X 
X /* New ioctl-codes */
@@ -192,8 +290,8 @@
X #define IIOCNETANM  _IO('I',5)
X #define IIOCNETDNM  _IO('I',6)
X #define IIOCNETGNM  _IO('I',7)
-#define IIOCGETSET  _IO('I',8)
-#define IIOCSETSET  _IO('I',9)
+#define IIOCGETSET  _IO('I',8) /* no longer supported */
+#define IIOCSETSET  _IO('I',9) /* no longer supported */
X #define IIOCSETVER  _IO('I',10)
X #define IIOCNETHUP  _IO('I',11)
X #define IIOCSETGST  _IO('I',12)
@@ -211,6 +309,8 @@
X #define IIOCNETALN  _IO('I',32)
X #define IIOCNETDLN  _IO('I',33)
X 
+#define IIOCNETGPN  _IO('I',34)
+
X #define IIOCDBGVAR  _IO('I',127)
X 
X #define IIOCDRVCTL  _IO('I',128)
@@ -238,6 +338,8 @@
X 
X #define ISDN_MODEM_ANZREG    23        /* Number of Modem-Registers        */
X #define ISDN_MSNLEN          20
+#define ISDN_LMSNLEN         255 /* Length of tty's Listen-MSN string */
+#define ISDN_CMSGLEN	     50	 /* Length of CONNECT-Message to add for Modem */
X 
X typedef struct {
X   char drvid[25];
@@ -256,8 +358,9 @@
X   int  outgoing;
X } isdn_net_ioctl_phone;
X 
-#define NET_DV 0x04 /* Data version for net_cfg     */
-#define TTY_DV 0x04 /* Data version for iprofd etc. */
+#define NET_DV 0x05 /* Data version for net_cfg       */
+#define TTY_DV 0x05 /* Data version for iprofd etc.   */
+#define INF_DV 0x01 /* Data version for /dev/isdninfo */
X 
X typedef struct {
X   char name[10];     /* Name of interface                     */
@@ -282,8 +385,17 @@
X   int  pppbind;      /* ippp device for bindings              */
X   int  chargeint;    /* Use fixed charge interval length      */
X   int  triggercps;   /* BogoCPS needed for triggering slave   */
+  int  dialtimeout;  /* Dial-Timeout                          */
+  int  dialwait;     /* Time to wait after failed dial        */
+  int  dialmode;     /* Flag: off / on / auto                 */
X } isdn_net_ioctl_cfg;
X 
+#define ISDN_NET_DIALMODE_MASK 0xC0  /* bits for status                   */
+#define  ISDN_NET_DM_OFF	0x00    /* this interface is stopped      */
+#define  ISDN_NET_DM_MANUAL	0x40    /* this interface is on (manual)  */
+#define  ISDN_NET_DM_AUTO	0x80    /* this interface is autodial     */
+#define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK)
+
X #ifdef __KERNEL__
X 
X #ifndef STANDALONE
@@ -331,6 +443,7 @@
X 
X #include <linux/isdnif.h>
X 
+
X #define ISDN_DRVIOCTL_MASK       0x7f  /* Mask for Device-ioctl */
X 
X /* Until now unused */
@@ -372,14 +485,17 @@
X #define ISDN_TIMER_NETHANGUP  32
X #define ISDN_TIMER_IPPP       64 
X #define ISDN_TIMER_KEEPALIVE 128 /* Cisco-Keepalive */
+#define ISDN_TIMER_CARRIER   256 /* Wait for Carrier */
X #define ISDN_TIMER_FAST      (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
X                               ISDN_TIMER_MODEMXMIT)
X #define ISDN_TIMER_SLOW      (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
-                              ISDN_TIMER_NETDIAL | ISDN_TIMER_KEEPALIVE)
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 39'
echo 'File patch-2.3.4 is continued in part 40'
echo 40 > _shar_seq_.tmp
#!/bin/sh
# this is part 47 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 47; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X 	 * anymore, the common case will execute the loop only once.
X 	 *
-	 * Or rather, it _would_ execute only once if it wasn't for
-	 * some extraneous wakeups that currently happen.
-	 *
X 	 * Subtle issue: "add_wait_queue_exclusive()" will be added
X 	 * after any current non-exclusive waiters, and we know that
X 	 * it will always _stay_ after any new non-exclusive waiters
@@ -1620,6 +1625,7 @@
X 	struct sock *newsk = NULL;
X 	int error;
X 
+	unlock_kernel();
X 	lock_sock(sk); 
X 
X 	/* We need to make sure that this socket is listening,
@@ -1650,16 +1656,17 @@
X 	sk->ack_backlog--; 
X 	if(sk->keepopen)
X 		tcp_inc_slow_timer(TCP_SLT_KEEPALIVE);
-
X 	release_sock(sk);
+	lock_kernel();
X 	return newsk;
X 
X out:
X 	/* sk should be in LISTEN state, thus accept can use sk->err for
-	 * internal purposes without stomping one anyone's feed.
+	 * internal purposes without stomping on anyone's feed.
X 	 */ 
X 	sk->err = error; 
X 	release_sock(sk);
+	lock_kernel();
X 	return newsk;
X }
X 
@@ -1782,6 +1789,8 @@
X void __init tcp_init(void)
X {
X 	struct sk_buff *skb = NULL;
+	unsigned long goal;
+	int order;
X 
X 	if(sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
X 		__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
@@ -1807,4 +1816,37 @@
X 						NULL, NULL);
X 	if(!tcp_timewait_cachep)
X 		panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
+
+	/* Size and allocate the main established and bind bucket
+	 * hash tables.
+	 *
+	 * The methodology is similar to that of the buffer cache.
+	 */
+	goal = num_physpages >> (20 - PAGE_SHIFT);
+	for(order = 5; (1UL << order) < goal; order++)
+		;
+	do {
+		tcp_ehash_size = (1UL << order) * PAGE_SIZE /
+			sizeof(struct sock *);
+		tcp_ehash = (struct sock **)
+			__get_free_pages(GFP_ATOMIC, order);
+	} while (tcp_ehash == NULL && --order > 4);
+
+	if (!tcp_ehash)
+		panic("Failed to allocate TCP established hash table\n");
+	memset(tcp_ehash, 0, tcp_ehash_size * sizeof(struct sock *));
+
+	do {
+		tcp_bhash_size = (1UL << order) * PAGE_SIZE /
+			sizeof(struct tcp_bind_bucket *);
+		tcp_bhash = (struct tcp_bind_bucket **)
+			__get_free_pages(GFP_ATOMIC, order);
+	} while (tcp_bhash == NULL && --order > 4);
+
+	if (!tcp_bhash)
+		panic("Failed to allocate TCP bind hash table\n");
+	memset(tcp_bhash, 0, tcp_bhash_size * sizeof(struct tcp_bind_bucket *));
+
+	printk("TCP: Hash tables configured (established %d bind %d)\n",
+	       tcp_ehash_size, tcp_bhash_size);
X }
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.3.3/linux/net/ipv4/tcp_input.c	Sat May 15 23:46:05 1999
+++ linux/net/ipv4/tcp_input.c	Mon May 31 22:07:43 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_input.c,v 1.165 1999/05/14 23:10:08 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.167 1999/05/29 22:37:54 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -914,8 +914,11 @@
X extern void tcp_tw_reschedule(struct tcp_tw_bucket *tw);
X extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
X 
+/* Must be called only from BH context. */
X void tcp_timewait_kill(struct tcp_tw_bucket *tw)
X {
+	SOCKHASH_LOCK_WRITE_BH();
+
X 	/* Unlink from various places. */
X 	if(tw->bind_next)
X 		tw->bind_next->bind_pprev = tw->bind_pprev;
@@ -933,6 +936,8 @@
X 	tw->sklist_next->sklist_prev = tw->sklist_prev;
X 	tw->sklist_prev->sklist_next = tw->sklist_next;
X 
+	SOCKHASH_UNLOCK_WRITE_BH();
+
X 	/* Ok, now free it up. */
X 	kmem_cache_free(tcp_timewait_cachep, tw);
X }
@@ -963,6 +968,7 @@
X 		struct sock *sk;
X 		struct tcp_func *af_specific = tw->af_specific;
X 		__u32 isn;
+		int ret;
X 
X 		isn = tw->rcv_nxt + 128000;
X 		if(isn == 0)
@@ -971,14 +977,25 @@
X 		tcp_timewait_kill(tw);
X 		sk = af_specific->get_sock(skb, th);
X 		if(sk == NULL ||
-		   !ipsec_sk_policy(sk,skb) ||
-		   atomic_read(&sk->sock_readers) != 0)
+		   !ipsec_sk_policy(sk,skb))
X 			return 0;
+
+		bh_lock_sock(sk);
+
+		/* Default is to discard the frame. */
+		ret = 0;
+
+		if(sk->lock.users)
+			goto out_unlock;
+
X 		skb_set_owner_r(skb, sk);
X 		af_specific = sk->tp_pinfo.af_tcp.af_specific;
+
X 		if(af_specific->conn_request(sk, skb, isn) < 0)
-			return 1; /* Toss a reset back. */
-		return 0; /* Discard the frame. */
+			ret = 1; /* Toss a reset back. */
+	out_unlock:
+		bh_unlock_sock(sk);
+		return ret;
X 	}
X 
X 	/* Check RST or SYN */
@@ -1031,7 +1048,7 @@
X 	sk->prot->inuse--;
X 
X 	/* Step 4: Hash TW into TIMEWAIT half of established hash table. */
-	head = &tcp_established_hash[sk->hashent + (TCP_HTABLE_SIZE/2)];
+	head = &tcp_ehash[sk->hashent + (tcp_ehash_size >> 1)];
X 	sktw = (struct sock *)tw;
X 	if((sktw->next = *head) != NULL)
X 		(*head)->pprev = &sktw->next;
@@ -1069,7 +1086,9 @@
X 		}
X #endif
X 		/* Linkage updates. */
+		SOCKHASH_LOCK_WRITE();
X 		tcp_tw_hashdance(sk, tw);
+		SOCKHASH_UNLOCK_WRITE();
X 
X 		/* Get the TIME_WAIT timeout firing. */
X 		tcp_tw_schedule(tw);
@@ -1819,7 +1838,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
@@ -2049,8 +2068,26 @@
X 		/* These use the socket TOS.. 
X 		 * might want to be the received TOS 
X 		 */
-		if(th->ack)
-			return 1;
+		if(th->ack) {
+			struct sock *realsk;
+			int ret;
+
+			realsk = tp->af_specific->get_sock(skb, th);
+			if(realsk == sk)
+				return 1;
+
+			bh_lock_sock(realsk);
+			ret = 0;
+			if(realsk->lock.users != 0) {
+				skb_orphan(skb);
+				sk_add_backlog(realsk, skb);
+			} else {
+				ret = tcp_rcv_state_process(realsk, skb,
+							    skb->h.th, skb->len);
+			}
+			bh_unlock_sock(realsk);
+			return ret;
+		}
X 		
X 		if(th->syn) {
X 			if(tp->af_specific->conn_request(sk, skb, 0) < 0)
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.3/linux/net/ipv4/tcp_ipv4.c	Fri May 14 18:55:32 1999
+++ linux/net/ipv4/tcp_ipv4.c	Mon May 31 22:07:43 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_ipv4.c,v 1.176 1999/05/12 11:24:46 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.178 1999/05/30 01:16:27 davem Exp $
X  *
X  *		IPv4 specific functions
X  *
@@ -90,12 +90,14 @@
X  * First half of the table is for sockets not in TIME_WAIT, second half
X  * is for TIME_WAIT sockets only.
X  */
-struct sock *tcp_established_hash[TCP_HTABLE_SIZE];
+struct sock **tcp_ehash;
+int tcp_ehash_size;
X 
X /* Ok, let's try this, I give up, we do need a local binding
X  * TCP hash as well as the others for fast bind/connect.
X  */
-struct tcp_bind_bucket *tcp_bound_hash[TCP_BHTABLE_SIZE];
+struct tcp_bind_bucket **tcp_bhash;
+int tcp_bhash_size;
X 
X /* All sockets in TCP_LISTEN state will be in here.  This is the only table
X  * where wildcard'd TCP sockets can exist.  Hash function here is just local
@@ -117,7 +119,7 @@
X static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
X 				 __u32 faddr, __u16 fport)
X {
-	return ((laddr ^ lport) ^ (faddr ^ fport)) & ((TCP_HTABLE_SIZE/2) - 1);
+	return ((laddr ^ lport) ^ (faddr ^ fport)) & ((tcp_ehash_size >> 1) - 1);
X }
X 
X static __inline__ int tcp_sk_hashfn(struct sock *sk)
@@ -136,8 +138,8 @@
X 	struct tcp_bind_bucket *tb;
X 	unsigned short snum = sk->num;
X 
-	SOCKHASH_LOCK();
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)]; tb; tb = tb->next) {
+	SOCKHASH_LOCK_WRITE();
+	for(tb = tcp_bhash[tcp_bhashfn(snum)]; tb; tb = tb->next) {
X 		if(tb->port == snum) {
X 			if(tb->owners == NULL &&
X 			   (tb->flags & TCPB_FLAG_LOCKED)) {
@@ -148,9 +150,10 @@
X 			break;
X 		}
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
+/* The sockhash lock must be held as a writer here. */
X struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
X {
X 	struct tcp_bind_bucket *tb;
@@ -158,7 +161,7 @@
X 	tb = kmem_cache_alloc(tcp_bucket_cachep, SLAB_ATOMIC);
X 	if(tb != NULL) {
X 		struct tcp_bind_bucket **head =
-			&tcp_bound_hash[tcp_bhashfn(snum)];
+			&tcp_bhash[tcp_bhashfn(snum)];
X 		tb->port = snum;
X 		tb->flags = TCPB_FLAG_LOCKED;
X 		tb->owners = NULL;
@@ -176,13 +179,18 @@
X  */
X static __inline__ int tcp_bucket_check(unsigned short snum)
X {
-	struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(snum)];
+	struct tcp_bind_bucket *tb;
+	int ret = 0;
+
+	SOCKHASH_LOCK_WRITE();
+	tb = tcp_bhash[tcp_bhashfn(snum)];
X 	for( ; (tb && (tb->port != snum)); tb = tb->next)
X 		;
X 	if(tb == NULL && tcp_bucket_create(snum) == NULL)
-		return 1;
-	else
-		return 0;
+		ret = 1;
+	SOCKHASH_UNLOCK_WRITE();
+
+	return ret;
X }
X #endif
X 
@@ -191,8 +199,8 @@
X 	struct tcp_bind_bucket *tb;
X 	int result = 0;
X 
-	SOCKHASH_LOCK();
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)];
+	SOCKHASH_LOCK_WRITE();
+	for(tb = tcp_bhash[tcp_bhashfn(snum)];
X 	    (tb && (tb->port != snum));
X 	    tb = tb->next)
X 		;
@@ -256,7 +264,7 @@
X 		}
X 	}
X go_like_smoke:
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X 	return result;
X }
X 
@@ -268,13 +276,13 @@
X 	int remaining = (high - low) + 1;
X 	int rover;
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	rover = tcp_port_rover;
X 	do {
X 		rover += 1;
X 		if((rover < low) || (rover > high))
X 			rover = low;
-		tb = tcp_bound_hash[tcp_bhashfn(rover)];
+		tb = tcp_bhash[tcp_bhashfn(rover)];
X 		for( ; tb; tb = tb->next) {
X 			if(tb->port == rover)
X 				goto next;
@@ -288,7 +296,7 @@
X 		rover = 0;
X 	if (tb != NULL)
X 		tb->flags |= TCPB_FLAG_GOODSOCKNUM;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X 
X 	return rover;
X }
@@ -298,20 +306,20 @@
X 	if (sk->state != TCP_CLOSE) {
X 		struct sock **skp;
X 
-		SOCKHASH_LOCK();
-		skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+		SOCKHASH_LOCK_WRITE();
+		skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
X 		if((sk->next = *skp) != NULL)
X 			(*skp)->pprev = &sk->next;
X 		*skp = sk;
X 		sk->pprev = skp;
X 		tcp_sk_bindify(sk);
-		SOCKHASH_UNLOCK();
+		SOCKHASH_UNLOCK_WRITE();
X 	}
X }
X 
X static void tcp_v4_unhash(struct sock *sk)
X {
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	if(sk->pprev) {
X 		if(sk->next)
X 			sk->next->pprev = sk->pprev;
@@ -320,14 +328,14 @@
X 		tcp_reg_zap(sk);
X 		tcp_sk_unbindify(sk);
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void tcp_v4_rehash(struct sock *sk)
X {
X 	unsigned char state;
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	state = sk->state;
X 	if(sk->pprev != NULL) {
X 		if(sk->next)
@@ -342,7 +350,7 @@
X 		if(state == TCP_LISTEN)
X 			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
X 		else
-			skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+			skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
X 
X 		if((sk->next = *skp) != NULL)
X 			(*skp)->pprev = &sk->next;
@@ -351,7 +359,7 @@
X 		if(state == TCP_LISTEN)
X 			tcp_sk_bindify(sk);
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X /* Don't inline this cruft.  Here are some nice properties to
@@ -395,10 +403,10 @@
X 
X /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
X  * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
- * It is assumed that this code only gets called from within NET_BH.
+ *
+ * The sockhash lock must be held as a reader here.
X  */
-static inline struct sock *__tcp_v4_lookup(struct tcphdr *th,
-					   u32 saddr, u16 sport,
+static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport,
X 					   u32 daddr, u16 dport, int dif)
X {
X 	TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
@@ -416,7 +424,7 @@
X 	 * have wildcards anyways.
X 	 */
X 	hash = tcp_hashfn(daddr, hnum, saddr, sport);
-	for(sk = tcp_established_hash[hash]; sk; sk = sk->next) {
+	for(sk = tcp_ehash[hash]; sk; sk = sk->next) {
X 		if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif)) {
X 			if (sk->state == TCP_ESTABLISHED)
X 				TCP_RHASH(sport) = sk;
@@ -424,7 +432,7 @@
X 		}
X 	}
X 	/* Must check for a TIME_WAIT'er before going to listener hash. */
-	for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next)
+	for(sk = tcp_ehash[hash+(tcp_ehash_size >> 1)]; sk; sk = sk->next)
X 		if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
X 			goto hit;
X 	sk = tcp_v4_lookup_listener(daddr, hnum, dif);
@@ -434,7 +442,13 @@
X 
X __inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
X {
-	return __tcp_v4_lookup(0, saddr, sport, daddr, dport, dif);
+	struct sock *sk;
+
+	SOCKHASH_LOCK_READ();
+	sk = __tcp_v4_lookup(saddr, sport, daddr, dport, dif);
+	SOCKHASH_UNLOCK_READ();
+
+	return sk;
X }
X 
X #ifdef CONFIG_IP_TRANSPARENT_PROXY
@@ -462,9 +476,12 @@
X 			paddr = idev->ifa_list->ifa_local;
X 	}
X 
-	/* This code must run only from NET_BH. */
+	/* We must obtain the sockhash lock here, we are always
+	 * in BH context.
+	 */
+	SOCKHASH_LOCK_READ_BH();
X 	{
-		struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(hnum)];
+		struct tcp_bind_bucket *tb = tcp_bhash[tcp_bhashfn(hnum)];
X 		for( ; (tb && tb->port != hnum); tb = tb->next)
X 			;
X 		if(tb == NULL)
@@ -505,7 +522,7 @@
X 	}
X next:
X 	if(firstpass--) {
-		struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(hpnum)];
+		struct tcp_bind_bucket *tb = tcp_bhash[tcp_bhashfn(hpnum)];
X 		for( ; (tb && tb->port != hpnum); tb = tb->next)
X 			;
X 		if(tb) {
@@ -514,6 +531,7 @@
X 		}
X 	}
X gotit:
+	SOCKHASH_UNLOCK_READ_BH();
X 	return result;
X }
X #endif /* CONFIG_IP_TRANSPARENT_PROXY */
@@ -540,21 +558,23 @@
X 	int retval = 1;
X 
X 	/* Freeze the hash while we snoop around. */
-	SOCKHASH_LOCK();
-	tb = tcp_bound_hash[tcp_bhashfn(snum)];
+	SOCKHASH_LOCK_READ();
+	tb = tcp_bhash[tcp_bhashfn(snum)];
X 	for(; tb; tb = tb->next) {
X 		if(tb->port == snum && tb->owners != NULL) {
X 			/* Almost certainly the re-use port case, search the real hashes
X 			 * so it actually scales.
X 			 */
-			sk = __tcp_v4_lookup(NULL, sk->daddr, sk->dport,
+			sk = __tcp_v4_lookup(sk->daddr, sk->dport,
X 					     sk->rcv_saddr, snum, sk->bound_dev_if);
+			SOCKHASH_UNLOCK_READ();
+
X 			if((sk != NULL) && (sk->state != TCP_LISTEN))
X 				retval = 0;
-			break;
+			return retval;
X 		}
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 	return retval;
X }
X 
@@ -727,16 +747,17 @@
X {
X 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
X 
-	if (atomic_read(&sk->sock_readers))
-		return;
-
-	/* Don't interested in TCP_LISTEN and open_requests (SYN-ACKs
+	/* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
X 	 * send out by Linux are always <576bytes so they should go through
X 	 * unfragmented).
X 	 */
X 	if (sk->state == TCP_LISTEN)
X 		return; 
X 
+	bh_lock_sock(sk);
+	if(sk->lock.users != 0)
+		goto out;
+
X 	/* We don't check in the destentry if pmtu discovery is forbidden
X 	 * on this route. We just assume that no packet_to_big packets
X 	 * are send back when pmtu discovery is not active.
@@ -744,7 +765,8 @@
X 	 * route, but I think that's acceptable.
X 	 */
X 	if (sk->dst_cache == NULL)
-		return;
+		goto out;
+
X 	ip_rt_update_pmtu(sk->dst_cache, mtu);
X 	if (sk->ip_pmtudisc != IP_PMTUDISC_DONT &&
X 	    tp->pmtu_cookie > sk->dst_cache->pmtu) {
@@ -757,6 +779,8 @@
X 		 */
X 		tcp_simple_retransmit(sk);
X 	} /* else let the usual retransmit timer handle it */
+out:
+	bh_unlock_sock(sk);
X }
X 
X /*
@@ -849,17 +873,6 @@
X 	switch (sk->state) {
X 		struct open_request *req, *prev;
X 	case TCP_LISTEN:
-		/* Prevent race conditions with accept() - 
-		 * ICMP is unreliable. 
-		 */
-		if (atomic_read(&sk->sock_readers)) {
-			net_statistics.LockDroppedIcmps++;
-			 /* If too many ICMPs get dropped on busy
-			  * servers this needs to be solved differently.
-			  */
-			return;
-		}
-
X 		/* The final ACK of the handshake should be already 
X 		 * handled in the new socket context, not here.
X 		 * Strictly speaking - an ICMP error for the final
@@ -869,12 +882,24 @@
X 		if (!no_flags && !th->syn && !th->ack)
X 			return;
X 
+		/* Prevent race conditions with accept() - 
+		 * ICMP is unreliable. 
+		 */
+		bh_lock_sock(sk);
+		if (sk->lock.users != 0) {
+			net_statistics.LockDroppedIcmps++;
+			 /* If too many ICMPs get dropped on busy
+			  * servers this needs to be solved differently.
+			  */
+			goto out_unlock;
+		}
+
X 		req = tcp_v4_search_req(tp, iph, th, &prev); 
X 		if (!req)
-			return;
+			goto out_unlock;
X 		if (seq != req->snt_isn) {
X 			net_statistics.OutOfWindowIcmps++;
-			return;
+			goto out_unlock;
X 		}
X 		if (req->sk) {	
X 			/* 
@@ -884,6 +909,7 @@
X 			 * but only with the next operation on the socket after
X 			 * accept. 
X 			 */
+			bh_unlock_sock(sk);
X 			sk = req->sk;
X 		} else {
X 			/* 
@@ -896,6 +922,8 @@
X 			tcp_synq_unlink(tp, req, prev);
X 			req->class->destructor(req);
X 			tcp_openreq_free(req);
+	out_unlock:
+			bh_unlock_sock(sk);
X 			return; 
X 		}
X 		break;
@@ -1025,9 +1053,10 @@
X {
X 	struct iphdr *iph = skb->nh.iph;
X 	struct tcphdr *th = (struct tcphdr *)(skb->nh.raw + iph->ihl*4);
-	struct sock *sk;
+	struct sock *sk = NULL;
X 	int i;
X 
+	SOCKHASH_LOCK_READ();
X 	for (i=0; i<TCP_LHTABLE_SIZE; i++) {
X 		for(sk = tcp_listening_hash[i]; sk; sk = sk->next) {
X 			struct open_request *dummy;
@@ -1035,10 +1064,12 @@
X 					      th, &dummy) &&
X 			    (!sk->bound_dev_if ||
X 			     sk->bound_dev_if == skb->dev->ifindex))
-				return sk;
+				goto out;
X 		}
X 	}
-	return NULL;
+out:
+	SOCKHASH_UNLOCK_READ();
+	return sk;
X }
X 
X /*
@@ -1319,7 +1350,8 @@
X 		/* Clone the TCP header template */
X 		newsk->dport = req->rmt_port;
X 
-		atomic_set(&newsk->sock_readers, 0);
+		sock_lock_init(newsk);
+
X 		atomic_set(&newsk->rmem_alloc, 0);
X 		skb_queue_head_init(&newsk->receive_queue);
X 		atomic_set(&newsk->wmem_alloc, 0);
@@ -1328,9 +1360,9 @@
X 
X 		newsk->done = 0;
X 		newsk->proc = 0;
-		newsk->pair = NULL;
-		skb_queue_head_init(&newsk->back_log);
+		newsk->backlog.head = newsk->backlog.tail = NULL;
X 		skb_queue_head_init(&newsk->error_queue);
+		newsk->write_space = tcp_write_space;
X #ifdef CONFIG_FILTER
X 		if ((filter = newsk->filter) != NULL)
X 			sk_filter_charge(newsk, filter);
@@ -1552,7 +1584,8 @@
X 	}
X 
X 	/* Check for SYN|ACK */
-	if (flg & __constant_htonl(0x00120000)) {
+	flg &= __constant_htonl(0x00120000);
+	if (flg) {
X 		struct open_request *req, *dummy; 
X 		struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
X 
@@ -1570,8 +1603,17 @@
X 	return sk; 
X }
X 
+/* The socket must have it's spinlock held when we get
+ * here.
+ *
+ * We have a potential double-lock case here, so even when
+ * doing backlog processing we use the BH locking scheme.
+ * This is because we cannot sleep with the original spinlock
+ * held.
+ */
X int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
X {
+	int need_unlock = 0;
X #ifdef CONFIG_FILTER
X 	struct sk_filter *filter = sk->filter;
X 	if (filter && sk_filter(skb, filter))
@@ -1591,7 +1633,6 @@
X 		return 0; 
X 	} 
X 
-
X 	if (sk->state == TCP_LISTEN) { 
X 		struct sock *nsk;
X 		
@@ -1604,17 +1645,22 @@
X 		 * otherwise we just shortcircuit this and continue with
X 		 * the new socket..
X 		 */
-		if (atomic_read(&nsk->sock_readers)) {
-			skb_orphan(skb);
-			__skb_queue_tail(&nsk->back_log, skb);
-			return 0;
+		if (nsk != sk) {
+			bh_lock_sock(nsk);
+			if (nsk->lock.users != 0) {
+				skb_orphan(skb);
+				sk_add_backlog(nsk, skb);
+				bh_unlock_sock(nsk);
+				return 0;
+			}
+			need_unlock = 1;
+			sk = nsk;
X 		}
-		sk = nsk;
X 	}
X 	
X 	if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
X 		goto reset;
-	return 0;
+	goto out_maybe_unlock;
X 
X reset:
X 	tcp_v4_send_reset(skb);
@@ -1625,6 +1671,9 @@
X 	 * might be destroyed here. This current version compiles correctly,
X 	 * but you have been warned.
X 	 */
+out_maybe_unlock:
+	if(need_unlock)
+		bh_unlock_sock(sk);
X 	return 0;
X }
X 
@@ -1636,6 +1685,7 @@
X {
X 	struct tcphdr *th;
X 	struct sock *sk;
+	int ret;
X 
X 	if (skb->pkt_type!=PACKET_HOST)
X 		goto discard_it;
@@ -1681,8 +1731,10 @@
X 					 IPCB(skb)->redirport, skb->dev->ifindex);
X 	else {
X #endif
-		sk = __tcp_v4_lookup(th, skb->nh.iph->saddr, th->source,
+		SOCKHASH_LOCK_READ_BH();
+		sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source,
X 				     skb->nh.iph->daddr, th->dest, skb->dev->ifindex);
+		SOCKHASH_UNLOCK_READ_BH();
X #ifdef CONFIG_IP_TRANSPARENT_PROXY
X 		if (!sk)
X 			sk = tcp_v4_search_proxy_openreq(skb);
@@ -1702,11 +1754,16 @@
X 
X 	if (sk->state == TCP_TIME_WAIT)
X 		goto do_time_wait;
-	if (!atomic_read(&sk->sock_readers))
-		return tcp_v4_do_rcv(sk, skb);
X 
-	__skb_queue_tail(&sk->back_log, skb);
-	return 0;
+	bh_lock_sock(sk);
+	ret = 0;
+	if (!sk->lock.users)
+		ret = tcp_v4_do_rcv(sk, skb);
+	else
+		sk_add_backlog(sk, skb);
+	bh_unlock_sock(sk);
+
+	return ret;
X 
X no_tcp_socket:
X 	tcp_v4_send_reset(skb);
@@ -1954,6 +2011,11 @@
X 	if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0)
X 		panic("Failed to create the TCP control socket.\n");
X 	tcp_socket->sk->allocation=GFP_ATOMIC;
-	tcp_socket->sk->num = 256;		/* Don't receive any data */
X 	tcp_socket->sk->ip_ttl = MAXTTL;
+
+	/* Unhash it so that IP input processing does not even
+	 * see it, we do not wish this socket to see incoming
+	 * packets.
+	 */
+	tcp_socket->sk->prot->unhash(tcp_socket->sk);
X }
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.3.3/linux/net/ipv4/tcp_output.c	Sat May 15 23:46:05 1999
+++ linux/net/ipv4/tcp_output.c	Wed May 26 18:14:38 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_output.c,v 1.109 1999/05/14 23:10:13 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.110 1999/05/27 00:37:45 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -36,6 +36,8 @@
X 
X #include <net/tcp.h>
X 
+#include <linux/smp_lock.h>
+
X extern int sysctl_tcp_timestamps;
X extern int sysctl_tcp_window_scaling;
X extern int sysctl_tcp_sack;
@@ -966,6 +968,7 @@
X 	/* Ok, now lock the socket before we make it visible to
X 	 * the incoming packet engine.
X 	 */
+	unlock_kernel();
X 	lock_sock(sk);
X 
X 	/* Socket identity change complete, no longer
@@ -993,6 +996,7 @@
X 
X 	/* Now, it is safe to release the socket. */
X 	release_sock(sk);
+	lock_kernel();
X }
X 
X /* Send out a delayed ack, the caller does the policy checking
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.3.3/linux/net/ipv4/tcp_timer.c	Mon May 17 09:55:23 1999
+++ linux/net/ipv4/tcp_timer.c	Wed May 26 18:14:38 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_timer.c,v 1.63 1999/05/15 23:02:21 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.64 1999/05/27 00:37:31 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -168,15 +168,16 @@
X {
X 	struct sock *sk = (struct sock*)data;
X 
+	bh_lock_sock(sk);
X 	if(!sk->zapped &&
X 	   sk->tp_pinfo.af_tcp.delayed_acks &&
X 	   sk->state != TCP_CLOSE) {
-		/* If socket is currently locked, defer the ACK. */
-		if (!atomic_read(&sk->sock_readers))
+		if (!sk->lock.users)
X 			tcp_send_ack(sk);
X 		else
X 			tcp_send_delayed_ack(&(sk->tp_pinfo.af_tcp), HZ/10);
X 	}
+	bh_unlock_sock(sk);
X }
X 
X void tcp_probe_timer(unsigned long data)
@@ -187,9 +188,11 @@
X 	if(sk->zapped) 
X 		return;
X 	
-	if (atomic_read(&sk->sock_readers)) {
+	bh_lock_sock(sk);
+	if (sk->lock.users) {
X 		/* Try again later. */
X 		tcp_reset_xmit_timer(sk, TIME_PROBE0, HZ/5);
+		bh_unlock_sock(sk);
X 		return;
X 	}
X 
@@ -216,6 +219,7 @@
X 		/* Only send another probe if we didn't close things up. */
X 		tcp_send_probe0(sk);
X 	}
+	bh_unlock_sock(sk);
X }
X 
X static __inline__ int tcp_keepopen_proc(struct sock *sk)
@@ -253,8 +257,9 @@
X {
X 	int i, reaped = 0;;
X 
-	for(i = 0; i < TCP_BHTABLE_SIZE; i++) {
-		struct tcp_bind_bucket *tb = tcp_bound_hash[i];
+	SOCKHASH_LOCK_WRITE_BH();
+	for(i = 0; i < tcp_bhash_size; i++) {
+		struct tcp_bind_bucket *tb = tcp_bhash[i];
X 
X 		while(tb) {
X 			struct tcp_bind_bucket *next = tb->next;
@@ -274,6 +279,8 @@
X 			tb = next;
X 		}
X 	}
+	SOCKHASH_UNLOCK_WRITE_BH();
+
X 	if(reaped != 0) {
X 		struct tcp_sl_timer *slt = (struct tcp_sl_timer *)data;
X 
@@ -294,8 +301,14 @@
X 	struct tcp_tw_bucket *tw;
X 	int killed = 0;
X 
+	/* The death-row tw chains are only ever touched
+	 * in BH context so no locking is needed.
+	 */
X 	tw = tcp_tw_death_row[tcp_tw_death_row_slot];
X 	tcp_tw_death_row[tcp_tw_death_row_slot] = NULL;
+	tcp_tw_death_row_slot =
+	  ((tcp_tw_death_row_slot + 1) & (TCP_TWKILL_SLOTS - 1));
+
X 	while(tw != NULL) {
X 		struct tcp_tw_bucket *next = tw->next_death;
X 
@@ -307,8 +320,6 @@
X 		struct tcp_sl_timer *slt = (struct tcp_sl_timer *)data;
X 		atomic_sub(killed, &slt->count);
X 	}
-	tcp_tw_death_row_slot =
-	  ((tcp_tw_death_row_slot + 1) & (TCP_TWKILL_SLOTS - 1));
X }
X 
X /* These are always called from BH context.  See callers in
@@ -319,12 +330,14 @@
X 	int slot = (tcp_tw_death_row_slot - 1) & (TCP_TWKILL_SLOTS - 1);
X 	struct tcp_tw_bucket **tpp = &tcp_tw_death_row[slot];
X 
+	SOCKHASH_LOCK_WRITE_BH();
X 	if((tw->next_death = *tpp) != NULL)
X 		(*tpp)->pprev_death = &tw->next_death;
X 	*tpp = tw;
X 	tw->pprev_death = tpp;
X 
X 	tw->death_slot = slot;
+	SOCKHASH_UNLOCK_WRITE_BH();
X 
X 	tcp_inc_slow_timer(TCP_SLT_TWKILL);
X }
@@ -335,6 +348,7 @@
X 	struct tcp_tw_bucket **tpp;
X 	int slot;
X 
+	SOCKHASH_LOCK_WRITE_BH();
X 	if(tw->next_death)
X 		tw->next_death->pprev_death = tw->pprev_death;
X 	*tw->pprev_death = tw->next_death;
@@ -348,16 +362,21 @@
X 	tw->pprev_death = tpp;
X 
X 	tw->death_slot = slot;
+	SOCKHASH_UNLOCK_WRITE_BH();
+
X 	/* Timer was incremented when we first entered the table. */
X }
X 
X /* This is for handling early-kills of TIME_WAIT sockets. */
X void tcp_tw_deschedule(struct tcp_tw_bucket *tw)
X {
+	SOCKHASH_LOCK_WRITE_BH();
X 	if(tw->next_death)
X 		tw->next_death->pprev_death = tw->pprev_death;
X 	*tw->pprev_death = tw->next_death;
X 	tw->pprev_death = NULL;
+	SOCKHASH_UNLOCK_WRITE_BH();
+
X 	tcp_dec_slow_timer(TCP_SLT_TWKILL);
X }
X 
@@ -399,20 +418,30 @@
X 	int count = 0;
X 	int i;
X 	
-	for(i = chain_start; i < (chain_start + ((TCP_HTABLE_SIZE/2) >> 2)); i++) {
-		struct sock *sk = tcp_established_hash[i];
+	SOCKHASH_LOCK_READ_BH();
+	for(i = chain_start; i < (chain_start + ((tcp_ehash_size >> 1) >> 2)); i++) {
+		struct sock *sk;
+
+		sk = tcp_ehash[i];
X 		while(sk) {
-			if(!atomic_read(&sk->sock_readers) && sk->keepopen) {
+			struct sock *next = sk->next;
+
+			bh_lock_sock(sk);
+			if (sk->keepopen && !sk->lock.users) {
+				SOCKHASH_UNLOCK_READ_BH();
X 				count += tcp_keepopen_proc(sk);
-				if(count == sysctl_tcp_max_ka_probes)
-					goto out;
+				SOCKHASH_LOCK_READ_BH();
X 			}
-			sk = sk->next;
+			bh_unlock_sock(sk);
+			if(count == sysctl_tcp_max_ka_probes)
+				goto out;
+			sk = next;
X 		}
X 	}
X out:
-	chain_start = ((chain_start + ((TCP_HTABLE_SIZE/2)>>2)) &
-		       ((TCP_HTABLE_SIZE/2) - 1));
+	SOCKHASH_UNLOCK_READ_BH();
+	chain_start = ((chain_start + ((tcp_ehash_size >> 1)>>2)) &
+		       ((tcp_ehash_size >> 1) - 1));
X }
X 
X /*
@@ -439,9 +468,11 @@
X 		return;
X 	}
X 
-	if (atomic_read(&sk->sock_readers)) {
+	bh_lock_sock(sk);
+	if (sk->lock.users) {
X 		/* Try again later */  
X 		tcp_reset_xmit_timer(sk, TIME_RETRANS, HZ/20);
+		bh_unlock_sock(sk);
X 		return;
X 	}
X 
@@ -508,12 +539,51 @@
X 	tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
X 
X 	tcp_write_timeout(sk);
+
+	bh_unlock_sock(sk);
X }
X 
X /*
X  *	Slow timer for SYN-RECV sockets
X  */
X 
+static void tcp_do_syn_queue(struct sock *sk, struct tcp_opt *tp, unsigned long now)
+{
+	struct open_request *prev, *req;
+
+	prev = (struct open_request *) &tp->syn_wait_queue;
+	for(req = tp->syn_wait_queue; req; ) {
+		struct open_request *next = req->dl_next;
+
+		if (! req->sk) {
+			tcp_synq_unlink(tp, req, prev);
+			if(req->retrans >= sysctl_tcp_retries1) {
+				(*req->class->destructor)(req);
+				tcp_dec_slow_timer(TCP_SLT_SYNACK);
+				tp->syn_backlog--;
+				tcp_openreq_free(req);
+				if (! tp->syn_wait_queue)
+					break;
+			} else {
+				unsigned long timeo;
+				struct open_request *rp;
+
+				(*req->class->rtx_syn_ack)(sk, req);
+				req->retrans++;
+				timeo = min((TCP_TIMEOUT_INIT << req->retrans),
+					    (120 * HZ));
+				req->expires = now + timeo;
+				rp = prev->dl_next;
+				tcp_synq_queue(tp, req);
+				if(rp != prev->dl_next)
+					prev = prev->dl_next;
+			}
+		} else
+			prev = req;
+		req = next;
+	}
+}
+
X /* This now scales very nicely. -DaveM */
X static void tcp_syn_recv_timer(unsigned long data)
X {
@@ -521,66 +591,21 @@
X 	unsigned long now = jiffies;
X 	int i;
X 
+	SOCKHASH_LOCK_READ_BH();
X 	for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
X 		sk = tcp_listening_hash[i];
-
X 		while(sk) {
X 			struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
X 			
X 			/* TCP_LISTEN is implied. */
-			if (!atomic_read(&sk->sock_readers) && tp->syn_wait_queue) {
-				struct open_request *prev = (struct open_request *)(&tp->syn_wait_queue);
-				struct open_request *req = tp->syn_wait_queue;
-				do {
-					struct open_request *conn;
-				  
-					conn = req;
-					req = req->dl_next;
-
-					if (conn->sk) {
-						prev = conn; 
-						continue; 
-					}
-
-					tcp_synq_unlink(tp, conn, prev);
-					if (conn->retrans >= sysctl_tcp_retries1) {
-#ifdef TCP_DEBUG
-						printk(KERN_DEBUG "syn_recv: "
-						       "too many retransmits\n");
-#endif
-						(*conn->class->destructor)(conn);
-						tcp_dec_slow_timer(TCP_SLT_SYNACK);
-						tp->syn_backlog--;
-						tcp_openreq_free(conn);
-
-						if (!tp->syn_wait_queue)
-							break;
-					} else {
-						unsigned long timeo;
-						struct open_request *op; 
-
-						(*conn->class->rtx_syn_ack)(sk, conn);
-
-						conn->retrans++;
-#ifdef TCP_DEBUG
-						printk(KERN_DEBUG "syn_ack rtx %d\n",
-						       conn->retrans);
-#endif
-						timeo = min((TCP_TIMEOUT_INIT 
-							     << conn->retrans),
-							    120*HZ);
-						conn->expires = now + timeo;
-						op = prev->dl_next; 
-						tcp_synq_queue(tp, conn);
-						if (op != prev->dl_next)
-							prev = prev->dl_next;
-					}
-					/* old prev still valid here */
-				} while (req);
-			}
+			bh_lock_sock(sk);
+			if (!sk->lock.users && tp->syn_wait_queue)
+				tcp_do_syn_queue(sk, tp, now);
+			bh_unlock_sock(sk);
X 			sk = sk->next;
X 		}
X 	}
+	SOCKHASH_UNLOCK_READ_BH();
X }
X 
X void tcp_sltimer_handler(unsigned long data)
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/timer.c linux/net/ipv4/timer.c
--- v2.3.3/linux/net/ipv4/timer.c	Mon Feb 22 09:05:55 1999
+++ linux/net/ipv4/timer.c	Wed May 26 18:14:38 1999
@@ -5,7 +5,7 @@
X  *
X  *		TIMER - implementation of software timers for IP.
X  *
- * Version:	$Id: timer.c,v 1.15 1999/02/22 13:54:29 davem Exp $
+ * Version:	$Id: timer.c,v 1.16 1999/05/27 00:37:39 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -69,13 +69,15 @@
X  */
X void net_timer (unsigned long data)
X {
-	struct sock *sk = (struct sock*)data;
+	struct sock *sk = (struct sock *) data;
X 	int why = sk->timeout;
X 
X 	/* Only process if socket is not in use. */
-	if (atomic_read(&sk->sock_readers)) {
+	bh_lock_sock(sk);
+	if (sk->lock.users) {
X 		/* Try again later. */ 
X 		mod_timer(&sk->timer, jiffies+HZ/20);
+		bh_unlock_sock(sk);
X 		return;
X 	}
X 
@@ -99,15 +101,15 @@
X 				printk (KERN_DEBUG "non CLOSE socket in time_done\n");
X 				break;
X 			}
-			destroy_sock (sk);
-			break;
+			destroy_sock(sk);
+			return;
X 
X 		case TIME_DESTROY:
X 			/* We've waited for a while for all the memory associated with
X 			 * the socket to be freed.
X 			 */
X 			destroy_sock(sk);
-			break;
+			return;
X 
X 		case TIME_CLOSE:
X 			/* We've waited long enough, close the socket. */
@@ -123,5 +125,8 @@
X 			printk ("net_timer: timer expired - reason %d is unknown\n", why);
X 			break;
X 	}
+
+	/* We only need to unlock if the socket was not destroyed. */
+	bh_unlock_sock(sk);
X }
X 
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.3.3/linux/net/ipv4/udp.c	Mon May 10 09:55:25 1999
+++ linux/net/ipv4/udp.c	Wed May 26 18:14:38 1999
@@ -5,7 +5,7 @@
X  *
X  *		The User Datagram Protocol (UDP).
X  *
- * Version:	$Id: udp.c,v 1.66 1999/05/08 20:00:25 davem Exp $
+ * Version:	$Id: udp.c,v 1.67 1999/05/27 00:37:50 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -128,7 +128,7 @@
X 	struct sock *sk2;
X 	int retval = 0, sk_reuse = sk->reuse;
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_READ();
X 	for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
X 		if((sk2->num == snum) && (sk2 != sk)) {
X 			unsigned char state = sk2->state;
@@ -158,7 +158,7 @@
X 			}
X 		}
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 	return retval;
X }
X 
@@ -180,7 +180,7 @@
X 	static int start = 0;
X 	int i, best, best_size_so_far;
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_READ();
X         if (start > sysctl_local_port_range[1] || start < sysctl_local_port_range[0])
X                 start = sysctl_local_port_range[0];
X 
@@ -223,15 +223,10 @@
X         }
X out:
X 	start = result;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 	return result;
X }
X 
-/* Last hit UDP socket cache, this is ipv4 specific so make it static. */
-static u32 uh_cache_saddr, uh_cache_daddr;
-static u16 uh_cache_dport, uh_cache_sport;
-static struct sock *uh_cache_sk = NULL;
-
X static void udp_v4_hash(struct sock *sk)
X {
X 	struct sock **skp;
@@ -240,11 +235,11 @@
X 	num &= (UDP_HTABLE_SIZE - 1);
X 	skp = &udp_hash[num];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	sk->next = *skp;
X 	*skp = sk;
X 	sk->hashent = num;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void udp_v4_unhash(struct sock *sk)
@@ -255,7 +250,7 @@
X 	num &= (UDP_HTABLE_SIZE - 1);
X 	skp = &udp_hash[num];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	while(*skp != NULL) {
X 		if(*skp == sk) {
X 			*skp = sk->next;
@@ -263,9 +258,7 @@
X 		}
X 		skp = &((*skp)->next);
X 	}
-	if(uh_cache_sk == sk)
-		uh_cache_sk = NULL;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void udp_v4_rehash(struct sock *sk)
@@ -277,7 +270,7 @@
X 	num &= (UDP_HTABLE_SIZE - 1);
X 	skp = &udp_hash[oldnum];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	while(*skp != NULL) {
X 		if(*skp == sk) {
X 			*skp = sk->next;
@@ -288,13 +281,11 @@
X 	sk->next = udp_hash[num];
X 	udp_hash[num] = sk;
X 	sk->hashent = num;
-	if(uh_cache_sk == sk)
-		uh_cache_sk = NULL;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
- * harder than this here plus the last hit cache. -DaveM
+ * harder than this. -DaveM
X  */
X struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
X {
@@ -341,21 +332,9 @@
X {
X 	struct sock *sk;
X 
-	if(!dif && uh_cache_sk		&&
-	   uh_cache_saddr == saddr	&&
-	   uh_cache_sport == sport	&&
-	   uh_cache_dport == dport	&&
-	   uh_cache_daddr == daddr)
-		return uh_cache_sk;
-
+	SOCKHASH_LOCK_READ();
X 	sk = udp_v4_lookup_longway(saddr, sport, daddr, dport, dif);
-	if(!dif) {
-		uh_cache_sk	= sk;
-		uh_cache_saddr	= saddr;
-		uh_cache_daddr	= daddr;
-		uh_cache_sport	= sport;
-		uh_cache_dport	= dport;
-	}
+	SOCKHASH_UNLOCK_READ();
X 	return sk;
X }
X 
@@ -393,7 +372,7 @@
X 			paddr = idev->ifa_list->ifa_local;
X 	}
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_READ();
X 	for(s = udp_v4_proxy_loop_init(hnum, hpnum, s, firstpass);
X 	    s != NULL;
X 	    s = udp_v4_proxy_loop_next(hnum, hpnum, s, firstpass)) {
@@ -431,7 +410,7 @@
X 			}
X 		}
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 	return result;
X }
X 
@@ -979,8 +958,6 @@
X 		sk->rcv_saddr=INADDR_ANY;
X 		sk->daddr=INADDR_ANY;
X 		sk->state = TCP_CLOSE;
-		if(uh_cache_sk == sk)
-			uh_cache_sk = NULL;
X 		return 0;
X 	}
X 
@@ -1005,9 +982,6 @@
X 	sk->dport = usin->sin_port;
X 	sk->state = TCP_ESTABLISHED;
X 
-	if(uh_cache_sk == sk)
-		uh_cache_sk = NULL;
-
X 	sk->dst_cache = &rt->u.dst;
X 	return(0);
X }
@@ -1015,6 +989,8 @@
X 
X static void udp_close(struct sock *sk, long timeout)
X {
+	bh_lock_sock(sk);
+
X 	/* See for explanation: raw_close in ipv4/raw.c */
X 	sk->state = TCP_CLOSE;
X 	udp_v4_unhash(sk);
diff -u --recursive --new-file v2.3.3/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.3/linux/net/ipv6/addrconf.c	Thu Mar 25 09:23:34 1999
+++ linux/net/ipv6/addrconf.c	Wed May 26 18:14:38 1999
@@ -5,7 +5,7 @@
X  *	Authors:
X  *	Pedro Roque		<ro...@di.fc.ul.pt>	
X  *
- *	$Id: addrconf.c,v 1.48 1999/03/25 10:04:43 davem Exp $
+ *	$Id: addrconf.c,v 1.49 1999/05/27 00:38:20 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
@@ -982,6 +982,7 @@
X 		return;
X 	}
X 
+	read_lock_bh(&dev_base_lock);
X         for (dev = dev_base; dev != NULL; dev = dev->next) {
X 		if (dev->ip_ptr && (dev->flags & IFF_UP)) {
X 			struct in_device * in_dev = dev->ip_ptr;
@@ -1000,6 +1001,7 @@
X 					flag |= IFA_HOST;
X 				}
X 
+				read_unlock_bh(&dev_base_lock);
X 				addrconf_lock();
X 				ifp = ipv6_add_addr(idev, &addr, flag);
X 				if (ifp) {
@@ -1011,9 +1013,11 @@
X 					ipv6_ifa_notify(RTM_NEWADDR, ifp);
X 				}
X 				addrconf_unlock();
+				read_lock_bh(&dev_base_lock);
X 			}
X 		}
X         }
+	read_unlock_bh(&dev_base_lock);
X }
X 
X static void init_loopback(struct device *dev)
@@ -1842,11 +1846,12 @@
X 	struct device *dev;
X 
X 	/* This takes sense only during module load. */
-
+	read_lock_bh(&dev_base_lock);
X 	for (dev = dev_base; dev; dev = dev->next) {
X 		if (!(dev->flags&IFF_UP))
X 			continue;
X 
+		read_unlock_bh(&dev_base_lock);
X 		switch (dev->type) {
X 		case ARPHRD_LOOPBACK:	
X 			init_loopback(dev);
@@ -1857,7 +1862,9 @@
X 		default:
X 			/* Ignore all other */
X 		}
+		read_lock_bh(&dev_base_lock);
X 	}
+	read_unlock_bh(&dev_base_lock);
X #endif
X 	
X #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.3/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c
--- v2.3.3/linux/net/ipv6/exthdrs.c	Mon May 17 09:55:23 1999
+++ linux/net/ipv6/exthdrs.c	Wed May 26 18:14:38 1999
@@ -7,7 +7,7 @@
X  *	Andi Kleen		<a...@muc.de>
X  *	Alexey Kuznetsov	<kuz...@ms2.inr.ac.ru>
X  *
- *	$Id: exthdrs.c,v 1.8 1998/10/03 09:38:27 davem Exp $
+ *	$Id: exthdrs.c,v 1.9 1999/05/17 23:47:35 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.3.3/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- v2.3.3/linux/net/ipv6/icmp.c	Sun Mar 21 07:22:00 1999
+++ linux/net/ipv6/icmp.c	Wed May 26 18:14:38 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.22 1999/05/19 22:06:39 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.3.3/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.3/linux/net/ipv6/mcast.c	Thu Mar 25 09:23:34 1999
+++ linux/net/ipv6/mcast.c	Wed May 26 18:14:38 1999
@@ -5,7 +5,7 @@
X  *	Authors:
X  *	Pedro Roque		<ro...@di.fc.ul.pt>	
X  *
- *	$Id: mcast.c,v 1.19 1999/03/25 10:04:50 davem Exp $
+ *	$Id: mcast.c,v 1.20 1999/05/27 00:38:23 davem Exp $
X  *
X  *	Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
X  *
@@ -615,6 +615,7 @@
X 	int len=0;
X 	struct device *dev;
X 	
+	read_lock_bh(&dev_base_lock);
X 	for (dev = dev_base; dev; dev = dev->next) {
X 		struct inet6_dev *idev;
X 
@@ -647,6 +648,8 @@
X 	*eof = 1;
X 
X done:
+	read_unlock_bh(&dev_base_lock);
+
X 	*start=buffer+(offset-begin);
X 	len-=(offset-begin);
X 	if(len>length)
diff -u --recursive --new-file v2.3.3/linux/net/ipv6/proc.c linux/net/ipv6/proc.c
--- v2.3.3/linux/net/ipv6/proc.c	Thu Aug 27 19:33:09 1998
+++ linux/net/ipv6/proc.c	Wed May 26 18:14:38 1999
@@ -7,7 +7,7 @@
X  *		PROC file system.  This is very similar to the IPv4 version,
X  *		except it reports the sockets in the INET6 address family.
X  *
- * Version:	$Id: proc.c,v 1.9 1998/08/26 12:05:11 davem Exp $
+ * Version:	$Id: proc.c,v 1.10 1999/05/27 00:38:14 davem Exp $
X  *
X  * Authors:	David S. Miller (da...@caip.rutgers.edu)
X  *
@@ -52,7 +52,7 @@
X 										/*144 */
X 
X 	pos = 149;
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_READ();
X 	sp = pro->sklist_next;
X 	while(sp != (struct sock *)pro) {
X 		struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sp;
@@ -72,6 +72,7 @@
X 		}
X 		destp = ntohs(sp->dport);
X 		srcp  = ntohs(sp->sport);
+
X 		if((format == 0) && (sp->state == TCP_TIME_WAIT)) {
X 			extern int tcp_tw_death_row_slot;
X 			int slot_dist;
@@ -85,10 +86,8 @@
X 				slot_dist = tcp_tw_death_row_slot - slot_dist;
X 			timer_expires	= jiffies + (slot_dist * TCP_TWKILL_PERIOD);
X 		} else {
-			timer_active1 = del_timer(&tp->retransmit_timer);
-			timer_active2 = del_timer(&sp->timer);
-			if(!timer_active1) tp->retransmit_timer.expires = 0;
-			if(!timer_active2) sp->timer.expires = 0;
+			timer_active1 = tp->retransmit_timer.prev != NULL;
+			timer_active2 = sp->timer.prev != NULL;
X 			timer_active = 0;
X 			timer_expires = (unsigned) -1;
X 		}
@@ -128,8 +127,6 @@
X 			((!tw_bucket && sp->socket) ?
X 			 sp->socket->inode->i_ino : 0));
X 
-		if(timer_active1) add_timer(&tp->retransmit_timer);
-		if(timer_active2) add_timer(&sp->timer);
X 		len += sprintf(buffer+len, "%-148s\n", tmpbuf);
X 		if(len >= length)
X 			break;
@@ -137,7 +134,7 @@
X 		sp = sp->sklist_next;
X 		i++;
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 
X 	begin = len - (pos - offset);
X 	*start = buffer + begin;
diff -u --recursive --new-file v2.3.3/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
--- v2.3.3/linux/net/ipv6/raw.c	Thu Apr 22 19:45:20 1999
+++ linux/net/ipv6/raw.c	Wed May 26 18:14:38 1999
@@ -7,7 +7,7 @@
X  *
X  *	Adapted from linux/net/ipv4/raw.c
X  *
- *	$Id: raw.c,v 1.24 1999/04/22 10:07:45 davem Exp $
+ *	$Id: raw.c,v 1.25 1999/05/27 00:38:16 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
@@ -50,11 +50,11 @@
X 
X 	num &= (RAWV6_HTABLE_SIZE - 1);
X 	skp = &raw_v6_htable[num];
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	sk->next = *skp;
X 	*skp = sk;
X 	sk->hashent = num;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void raw_v6_unhash(struct sock *sk)
@@ -65,7 +65,7 @@
X 	num &= (RAWV6_HTABLE_SIZE - 1);
X 	skp = &raw_v6_htable[num];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	while(*skp != NULL) {
X 		if(*skp == sk) {
X 			*skp = sk->next;
@@ -73,7 +73,7 @@
X 		}
X 		skp = &((*skp)->next);
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void raw_v6_rehash(struct sock *sk)
@@ -85,7 +85,7 @@
X 	num &= (RAWV6_HTABLE_SIZE - 1);
X 	skp = &raw_v6_htable[oldnum];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	while(*skp != NULL) {
X 		if(*skp == sk) {
X 			*skp = sk->next;
@@ -96,7 +96,7 @@
X 	sk->next = raw_v6_htable[num];
X 	raw_v6_htable[num] = sk;
X 	sk->hashent = num;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static __inline__ int inet6_mc_check(struct sock *sk, struct in6_addr *addr)
@@ -631,6 +631,8 @@
X 
X static void rawv6_close(struct sock *sk, long timeout)
X {
+	bh_lock_sock(sk);
+
X 	/* See for explanation: raw_close in ipv4/raw.c */
X 	sk->state = TCP_CLOSE;
X 	raw_v6_unhash(sk);
diff -u --recursive --new-file v2.3.3/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.3.3/linux/net/ipv6/tcp_ipv6.c	Fri Apr 23 18:39:47 1999
+++ linux/net/ipv6/tcp_ipv6.c	Wed May 26 18:14:38 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.106 1999/05/27 01:12:44 davem Exp $
X  *
X  *	Based on: 
X  *	linux/net/ipv4/tcp.c
@@ -67,7 +67,7 @@
X 	int hashent = (lport ^ fport);
X 
X 	hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
-	return (hashent & ((TCP_HTABLE_SIZE/2) - 1));
+	return (hashent & ((tcp_ehash_size >> 1) - 1));
X }
X 
X static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
@@ -89,8 +89,8 @@
X 	struct tcp_bind_bucket *tb;
X 	int result = 0;
X 
-	SOCKHASH_LOCK();
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)];
+	SOCKHASH_LOCK_WRITE();
+	for(tb = tcp_bhash[tcp_bhashfn(snum)];
X 	    (tb && (tb->port != snum));
X 	    tb = tb->next)
X 		;
@@ -156,7 +156,7 @@
X 		}
X 	}
X go_like_smoke:
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X 	return result;
X }
X 
@@ -172,20 +172,20 @@
X 	if(sk->state != TCP_CLOSE) {
X 		struct sock **skp;
X 
-		SOCKHASH_LOCK();
-		skp = &tcp_established_hash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
+		SOCKHASH_LOCK_WRITE();
+		skp = &tcp_ehash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
X 		if((sk->next = *skp) != NULL)
X 			(*skp)->pprev = &sk->next;
X 		*skp = sk;
X 		sk->pprev = skp;
X 		tcp_sk_bindify(sk);
-		SOCKHASH_UNLOCK();
+		SOCKHASH_UNLOCK_WRITE();
X 	}
X }
X 
X static void tcp_v6_unhash(struct sock *sk)
X {
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	if(sk->pprev) {
X 		if(sk->next)
X 			sk->next->pprev = sk->pprev;
@@ -194,14 +194,14 @@
X 		tcp_sk_unbindify(sk);
X 		tcp_reg_zap(sk);
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void tcp_v6_rehash(struct sock *sk)
X {
X 	unsigned char state;
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	state = sk->state;
X 	if(sk->pprev != NULL) {
X 		if(sk->next)
@@ -216,7 +216,7 @@
X 		if(state == TCP_LISTEN)
X 			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
X 		else
-			skp = &tcp_established_hash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
+			skp = &tcp_ehash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
X 
X 		if((sk->next = *skp) != NULL)
X 			(*skp)->pprev = &sk->next;
@@ -225,7 +225,7 @@
X 		if(state == TCP_LISTEN)
X 			tcp_sk_bindify(sk);
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum, int dif)
@@ -264,10 +264,10 @@
X 
X /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
X  * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
- * It is assumed that this code only gets called from within NET_BH.
+ *
+ * The sockhash lock must be held as a reader here.
X  */
-static inline struct sock *__tcp_v6_lookup(struct tcphdr *th,
-					   struct in6_addr *saddr, u16 sport,
+static inline struct sock *__tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
X 					   struct in6_addr *daddr, u16 dport,
X 					   int dif)
X {
@@ -285,7 +285,7 @@
X 	 * have wildcards anyways.
X 	 */
X 	hash = tcp_v6_hashfn(daddr, hnum, saddr, sport);
-	for(sk = tcp_established_hash[hash]; sk; sk = sk->next) {
+	for(sk = tcp_ehash[hash]; sk; sk = sk->next) {
X 		/* For IPV6 do the cheaper port and family tests first. */
X 		if(TCP_IPV6_MATCH(sk, saddr, daddr, ports, dif)) {
X 			if (sk->state == TCP_ESTABLISHED)
@@ -294,7 +294,7 @@
X 		}
X 	}
X 	/* Must check for a TIME_WAIT'er before going to listener hash. */
-	for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next) {
+	for(sk = tcp_ehash[hash+(tcp_ehash_size >> 1)]; sk; sk = sk->next) {
X 		if(*((__u32 *)&(sk->dport))	== ports	&&
X 		   sk->family			== PF_INET6) {
X 			struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
@@ -309,7 +309,13 @@
X 	return sk;
X }
X 
-#define tcp_v6_lookup(sa, sp, da, dp, dif) __tcp_v6_lookup((0),(sa),(sp),(da),(dp),(dif))
+#define tcp_v6_lookup(sa, sp, da, dp, dif) \
+({	struct sock *___sk; \
+	SOCKHASH_LOCK_READ(); \
+	___sk = __tcp_v6_lookup((sa),(sp),(da),(dp),(dif)); \
+	SOCKHASH_UNLOCK_READ(); \
+	___sk; \
+})
X 
X static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
X 				   struct in6_addr *saddr, 
@@ -344,24 +350,26 @@
X 	int retval = 1;
X 
X 	/* Freeze the hash while we snoop around. */
-	SOCKHASH_LOCK();
-	tb = tcp_bound_hash[tcp_bhashfn(snum)];
+	SOCKHASH_LOCK_READ();
+	tb = tcp_bhash[tcp_bhashfn(snum)];
X 	for(; tb; tb = tb->next) {
X 		if(tb->port == snum && tb->owners != NULL) {
X 			/* Almost certainly the re-use port case, search the real hashes
X 			 * so it actually scales.  (we hope that all ipv6 ftp servers will
X 			 * use passive ftp, I just cover this case for completeness)
X 			 */
-			sk = __tcp_v6_lookup(NULL, &sk->net_pinfo.af_inet6.daddr,
+			sk = __tcp_v6_lookup(&sk->net_pinfo.af_inet6.daddr,
X 					     sk->dport,
X 					     &sk->net_pinfo.af_inet6.rcv_saddr, snum,
X 					     sk->bound_dev_if);
+			SOCKHASH_UNLOCK_READ();
+
X 			if((sk != NULL) && (sk->state != TCP_LISTEN))
X 				retval = 0;
-			break;
+			return retval;
X 		}
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 	return retval;
X }
X 
@@ -551,7 +559,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 }
@@ -628,11 +636,14 @@
X 	if (type == ICMPV6_PKT_TOOBIG) {
X 		struct dst_entry *dst = NULL;
X 
-		if (atomic_read(&sk->sock_readers))
+		if (sk->state == TCP_LISTEN)
X 			return;
X 
-		if (sk->state == TCP_LISTEN)
+		bh_lock_sock(sk);
+		if(sk->lock.users) {
+			bh_unlock_sock(sk);
X 			return;
+		}
X 
X 		/* icmp should have updated the destination cache entry */
X 		if (sk->dst_cache)
@@ -664,7 +675,7 @@
X 			tcp_simple_retransmit(sk);
X 		} /* else let the usual retransmit timer handle it */
X 		dst_release(dst);
-		return;
+		bh_unlock_sock(sk);
X 	}
X 
X 	icmpv6_err_convert(type, code, &err);
@@ -674,11 +685,13 @@
X 		struct open_request *req, *prev;
X 		struct ipv6hdr hd;
X 	case TCP_LISTEN:
-		if (atomic_read(&sk->sock_readers)) {
+		bh_lock_sock(sk);
+		if (sk->lock.users) {
X 			net_statistics.LockDroppedIcmps++;
X 			 /* If too many ICMPs get dropped on busy
X 			  * servers this needs to be solved differently.
X 			  */
+			bh_unlock_sock(sk);
X  			return;
X 		}
X 
@@ -686,20 +699,22 @@
X 		ipv6_addr_copy(&hd.saddr, saddr);
X 		ipv6_addr_copy(&hd.daddr, daddr); 
X 		req = tcp_v6_search_req(tp, &hd, th, tcp_v6_iif(skb), &prev);
-		if (!req)
-			return;
-		if (seq != req->snt_isn) {
+		if (!req || (seq != req->snt_isn)) {
X 			net_statistics.OutOfWindowIcmps++;
+			bh_unlock_sock(sk);
X 			return;
X 		}
X 		if (req->sk) {
+			bh_unlock_sock(sk);
X 			sk = req->sk; /* report error in accept */
X 		} else {
X 			tp->syn_backlog--;
X 			tcp_synq_unlink(tp, req, prev);
X 			req->class->destructor(req);
X 			tcp_openreq_free(req);
+			bh_unlock_sock(sk);
X 		}
+
X 		/* FALL THROUGH */ 
X 	case TCP_SYN_SENT:
X 	case TCP_SYN_RECV:  /* Cannot happen */ 
@@ -1210,12 +1225,20 @@
X 	return sk;
X }
X 
+/* The socket must have it's spinlock held when we get
+ * here.
+ *
+ * We have a potential double-lock case here, so even when
+ * doing backlog processing we use the BH locking scheme.
+ * This is because we cannot sleep with the original spinlock
+ * held.
+ */
X static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
X {
X #ifdef CONFIG_FILTER
X 	struct sk_filter *filter;
X #endif
-	int users = 0;
+	int users = 0, need_unlock = 0;
X 
X 	/* Imagine: socket is IPv6. IPv4 packet arrives,
X 	   goes to IPv4 receive handler and backlogged.
@@ -1286,19 +1309,24 @@
X 		 * otherwise we just shortcircuit this and continue with
X 		 * the new socket..
X 		 */
-		if (atomic_read(&nsk->sock_readers)) {
-			skb_orphan(skb);
-			__skb_queue_tail(&nsk->back_log, skb);
-			return 0;
+		if(nsk != sk) {
+			bh_lock_sock(nsk);
+			if (nsk->lock.users) {
+				skb_orphan(skb);
+				sk_add_backlog(nsk, skb);
+				bh_unlock_sock(nsk);
+				return 0;
+			}
+			need_unlock = 1;
+			sk = nsk;
X 		}
-		sk = nsk;
X 	}
X 
X 	if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
X 		goto reset;
X 	if (users)
X 		goto ipv6_pktoptions;
-	return 0;
+	goto out_maybe_unlock;
X 
X reset:
X 	tcp_v6_send_reset(skb);
@@ -1306,7 +1334,7 @@
X 	if (users)
X 		kfree_skb(skb);
X 	kfree_skb(skb);
-	return 0;
+	goto out_maybe_unlock;
X 
X ipv6_pktoptions:
X 	/* Do you ask, what is it?
@@ -1335,6 +1363,9 @@
X 
X 	if (skb)
X 		kfree_skb(skb);
+out_maybe_unlock:
+	if (need_unlock)
+		bh_unlock_sock(sk);
X 	return 0;
X }
X 
@@ -1344,6 +1375,7 @@
X 	struct sock *sk;
X 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
X 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
+	int ret;
X 
X 	th = skb->h.th;
X 
@@ -1383,7 +1415,9 @@
X 		/* CHECKSUM_UNNECESSARY */
X 	};
X 
-	sk = __tcp_v6_lookup(th, saddr, th->source, daddr, th->dest, tcp_v6_iif(skb));
+	SOCKHASH_LOCK_READ_BH();
+	sk = __tcp_v6_lookup(saddr, th->source, daddr, th->dest, tcp_v6_iif(skb));
+	SOCKHASH_UNLOCK_READ_BH();
X 
X 	if (!sk)
X 		goto no_tcp_socket;
@@ -1396,11 +1430,15 @@
X 	if(sk->state == TCP_TIME_WAIT)
X 		goto do_time_wait;
X 
-	if (!atomic_read(&sk->sock_readers))
-		return tcp_v6_do_rcv(sk, skb);
+	bh_lock_sock(sk);
+	ret = 0;
+	if (!sk->lock.users)
+		ret = tcp_v6_do_rcv(sk, skb);
+	else
+		sk_add_backlog(sk, skb);
+	bh_unlock_sock(sk);
X 
-	__skb_queue_tail(&sk->back_log, skb);
-	return(0);
+	return ret;
X 
X no_tcp_socket:
X 	tcp_v6_send_reset(skb);
diff -u --recursive --new-file v2.3.3/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.3.3/linux/net/ipv6/udp.c	Mon May 10 09:55:25 1999
+++ linux/net/ipv6/udp.c	Wed May 26 18:14:38 1999
@@ -7,7 +7,7 @@
X  *
X  *	Based on linux/ipv4/udp.c
X  *
- *	$Id: udp.c,v 1.40 1999/05/08 20:00:32 davem Exp $
+ *	$Id: udp.c,v 1.41 1999/05/27 00:38:18 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
@@ -55,7 +55,7 @@
X 	int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
X 	int retval = 0, sk_reuse = sk->reuse;
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_READ();
X 	for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
X 		if((sk2->num == snum) && (sk2 != sk)) {
X 			unsigned char state = sk2->state;
@@ -86,7 +86,7 @@
X 			}
X 		}
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_READ();
X 	return retval;
X }
X 
@@ -98,11 +98,11 @@
X 	num &= (UDP_HTABLE_SIZE - 1);
X 	skp = &udp_hash[num];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	sk->next = *skp;
X 	*skp = sk;
X 	sk->hashent = num;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void udp_v6_unhash(struct sock *sk)
@@ -113,7 +113,7 @@
X 	num &= (UDP_HTABLE_SIZE - 1);
X 	skp = &udp_hash[num];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	while(*skp != NULL) {
X 		if(*skp == sk) {
X 			*skp = sk->next;
@@ -121,7 +121,7 @@
X 		}
X 		skp = &((*skp)->next);
X 	}
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static void udp_v6_rehash(struct sock *sk)
@@ -133,7 +133,7 @@
X 	num &= (UDP_HTABLE_SIZE - 1);
X 	skp = &udp_hash[oldnum];
X 
-	SOCKHASH_LOCK();
+	SOCKHASH_LOCK_WRITE();
X 	while(*skp != NULL) {
X 		if(*skp == sk) {
X 			*skp = sk->next;
@@ -144,7 +144,7 @@
X 	sk->next = udp_hash[num];
X 	udp_hash[num] = sk;
X 	sk->hashent = num;
-	SOCKHASH_UNLOCK();
+	SOCKHASH_UNLOCK_WRITE();
X }
X 
X static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
@@ -154,6 +154,7 @@
X 	unsigned short hnum = ntohs(dport);
X 	int badness = -1;
X 
+	SOCKHASH_LOCK_READ();
X 	for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) {
X 		if((sk->num == hnum)		&&
X 		   (sk->family == PF_INET6)	&&
@@ -189,6 +190,7 @@
X 			}
X 		}
X 	}
+	SOCKHASH_UNLOCK_READ();
X 	return result;
X }
X 
@@ -331,6 +333,8 @@
X 
X static void udpv6_close(struct sock *sk, long timeout)
X {
+	bh_lock_sock(sk);
+
X 	/* See for explanation: raw_close in ipv4/raw.c */
X 	sk->state = TCP_CLOSE;
X 	udp_v6_unhash(sk);
diff -u --recursive --new-file v2.3.3/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.3/linux/net/irda/af_irda.c	Fri May 14 18:55:32 1999
+++ linux/net/irda/af_irda.c	Sun May 30 10:28:16 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:   Tue May 11 12:42:26 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 DECLARE_WAIT_QUEUE_HEAD(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;
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 47'
echo 'File patch-2.3.4 is continued in part 48'
echo 48 > _shar_seq_.tmp
#!/bin/sh
# this is part 50 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 50; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X 		      ": irlmp_close_slap(self->lsap)\n");
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c
--- v2.3.3/linux/net/irda/irlpt/irlpt_srvr.c	Thu May  6 16:40:53 1999
+++ linux/net/irda/irlpt/irlpt_srvr.c	Sun May 30 10:27: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.3.3/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.3/linux/net/irda/irmod.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irmod.c	Sun May 30 10:27:04 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:   Mon May 10 15:28:49 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 
@@ -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.3.3/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.3.3/linux/net/irda/irproc.c	Mon May 10 13:01:21 1999
+++ linux/net/irda/irproc.c	Sun May 30 10:27: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.3.3/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.3.3/linux/net/irda/irsysctl.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irsysctl.c	Sun May 30 10:27: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.3.3/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.3.3/linux/net/irda/irttp.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irttp.c	Sun May 30 10:27:04 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 10 17:12:53 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 
@@ -48,8 +48,10 @@
X 					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 
@@ -337,6 +339,7 @@
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 		
@@ -360,8 +363,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 	
@@ -472,7 +475,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, 
@@ -655,15 +658,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 +693,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 +725,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 +744,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
@@ -797,9 +801,9 @@
X 	skb_pull(skb, TTP_HEADER);
X 
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 +813,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 +832,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 
@@ -850,7 +856,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 = 
@@ -878,7 +884,7 @@
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 +915,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 +944,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 +1083,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 +1361,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
diff -u --recursive --new-file v2.3.3/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.3.3/linux/net/irda/qos.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/qos.c	Sun May 30 10:27: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.3.3/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.3.3/linux/net/irda/wrapper.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/wrapper.c	Sun May 30 10:27:04 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:   Sun May  2 21:58:00 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,159 @@
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)
+ *
+ *    
+ *
+ */
+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;
+		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 = 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)
+ *
+ *    
+ *
+ */
+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.3.3/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.3.3/linux/net/netrom/nr_route.c	Fri Oct  9 11:56:59 1998
+++ linux/net/netrom/nr_route.c	Tue May 25 13:06:35 1999
@@ -564,10 +564,13 @@
X {
X 	struct device *dev, *first = NULL;
X 
-	for (dev = dev_base; dev != NULL; dev = dev->next)
+	read_lock_bh(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
X 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
X 			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
X 				first = dev;
+	}
+	read_unlock_bh(&dev_base_lock);
X 
X 	return first;
X }
@@ -579,11 +582,14 @@
X {
X 	struct device *dev;
X 
-	for (dev = dev_base; dev != NULL; dev = dev->next)
+	read_lock_bh(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
X 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0)
-			return dev;
-
-	return NULL;
+			goto out;
+	}
+out:
+	read_unlock_bh(&dev_base_lock);
+	return dev;
X }
X 
X static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters)
diff -u --recursive --new-file v2.3.3/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.3/linux/net/netsyms.c	Sat Apr 24 17:51:48 1999
+++ linux/net/netsyms.c	Mon May 31 22:07:43 1999
@@ -106,10 +106,17 @@
X EXPORT_SYMBOL(skb_over_panic);
X EXPORT_SYMBOL(skb_under_panic);
X 
+/* Socket layer global data */
+EXPORT_SYMBOL(sockhash_lock);
+
X /* Socket layer registration */
X EXPORT_SYMBOL(sock_register);
X EXPORT_SYMBOL(sock_unregister);
X 
+/* Socket locking */
+EXPORT_SYMBOL(lock_sock);
+EXPORT_SYMBOL(release_sock);
+
X /* Socket layer support routines */
X EXPORT_SYMBOL(memcpy_fromiovec);
X EXPORT_SYMBOL(memcpy_tokerneliovec);
@@ -156,7 +163,6 @@
X EXPORT_SYMBOL(net_families);
X EXPORT_SYMBOL(sock_kmalloc);
X EXPORT_SYMBOL(sock_kfree_s);
-EXPORT_SYMBOL(skb_queue_lock);
X 
X #ifdef CONFIG_FILTER
X EXPORT_SYMBOL(sk_run_filter);
@@ -187,7 +193,6 @@
X /*	dst_entry	*/
X EXPORT_SYMBOL(dst_alloc);
X EXPORT_SYMBOL(__dst_free);
-EXPORT_SYMBOL(dst_total);
X EXPORT_SYMBOL(dst_destroy);
X 
X /*	misc. support routines */
@@ -243,7 +248,6 @@
X EXPORT_SYMBOL(__ip_finish_output);
X EXPORT_SYMBOL(inet_dgram_ops);
X EXPORT_SYMBOL(ip_cmsg_recv);
-EXPORT_SYMBOL(__release_sock);
X 
X /* Route manipulation */
X EXPORT_SYMBOL(ip_rt_ioctl);
@@ -279,9 +283,11 @@
X 
X /* Socket demultiplexing. */
X EXPORT_SYMBOL(tcp_good_socknum);
-EXPORT_SYMBOL(tcp_established_hash);
+EXPORT_SYMBOL(tcp_ehash);
+EXPORT_SYMBOL(tcp_ehash_size);
X EXPORT_SYMBOL(tcp_listening_hash);
-EXPORT_SYMBOL(tcp_bound_hash);
+EXPORT_SYMBOL(tcp_bhash);
+EXPORT_SYMBOL(tcp_bhash_size);
X EXPORT_SYMBOL(udp_good_socknum);
X EXPORT_SYMBOL(udp_hash);
X 
@@ -470,6 +476,7 @@
X EXPORT_SYMBOL(netdev_fc_xoff);
X #endif
X EXPORT_SYMBOL(dev_base);
+EXPORT_SYMBOL(dev_base_lock);
X EXPORT_SYMBOL(dev_close);
X EXPORT_SYMBOL(dev_mc_add);
X EXPORT_SYMBOL(dev_mc_delete);
diff -u --recursive --new-file v2.3.3/linux/net/rose/rose_route.c linux/net/rose/rose_route.c
--- v2.3.3/linux/net/rose/rose_route.c	Wed Oct  7 15:52:55 1998
+++ linux/net/rose/rose_route.c	Tue May 25 13:06:35 1999
@@ -543,10 +543,13 @@
X {
X 	struct device *dev, *first = NULL;
X 
-	for (dev = dev_base; dev != NULL; dev = dev->next)
+	read_lock_bh(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
X 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
X 			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
X 				first = dev;
+	}
+	read_unlock_bh(&dev_base_lock);
X 
X 	return first;
X }
@@ -558,11 +561,14 @@
X {
X 	struct device *dev;
X 
-	for (dev = dev_base; dev != NULL; dev = dev->next)
+	read_lock_bh(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
X 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
-			return dev;
-
-	return NULL;
+			goto out;
+	}
+out:
+	read_unlock_bh(&dev_base_lock);
+	return dev;
X }
X 
X struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neigh)
diff -u --recursive --new-file v2.3.3/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.3.3/linux/net/sched/sch_api.c	Sun Mar 21 07:22:00 1999
+++ linux/net/sched/sch_api.c	Tue May 25 13:06:35 1999
@@ -713,6 +713,7 @@
X 
X 	s_idx = cb->args[0];
X 	s_q_idx = q_idx = cb->args[1];
+	read_lock_bh(&dev_base_lock);
X 	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
X 		if (idx < s_idx)
X 			continue;
@@ -729,6 +730,8 @@
X 	}
X 
X done:
+	read_unlock_bh(&dev_base_lock);
+
X 	cb->args[0] = idx;
X 	cb->args[1] = q_idx;
X 
diff -u --recursive --new-file v2.3.3/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
--- v2.3.3/linux/net/sched/sch_generic.c	Sun Mar 21 07:22:00 1999
+++ linux/net/sched/sch_generic.c	Tue May 25 13:06:35 1999
@@ -96,8 +96,10 @@
X 		struct Qdisc *q = (struct Qdisc*)h;
X 		struct device *dev = q->dev;
X 
+		spin_lock_bh(&dev->xmit_lock);
X 		while (!dev->tbusy && (res = qdisc_restart(dev)) < 0)
X 			/* NOTHING */;
+		spin_unlock_bh(&dev->xmit_lock);
X 
X 		/* An explanation is necessary here.
X 		   qdisc_restart called dev->hard_start_xmit,
@@ -131,8 +133,11 @@
X 	for (h = qdisc_head.forw; h != &qdisc_head; h = h->forw) {
X 		struct Qdisc *q = (struct Qdisc*)h;
X 		struct device *dev = q->dev;
+
+		spin_lock_bh(&dev->xmit_lock);
X 		if (dev->tbusy && jiffies - q->tx_last > q->tx_timeo)
X 			qdisc_restart(dev);
+		spin_unlock_bh(&dev->xmit_lock);
X 	}
X 	dev_watchdog.expires = jiffies + 5*HZ;
X 	add_timer(&dev_watchdog);
diff -u --recursive --new-file v2.3.3/linux/net/socket.c linux/net/socket.c
--- v2.3.3/linux/net/socket.c	Fri May 14 18:55:32 1999
+++ linux/net/socket.c	Tue May 25 13:06:35 1999
@@ -131,6 +131,11 @@
X static int sockets_in_use  = 0;
X 
X /*
+ *	Socket hashing lock.
+ */
+rwlock_t sockhash_lock = RW_LOCK_UNLOCKED;
+
+/*
X  *	Support routines. Move socket addresses back and forth across the kernel/user
X  *	divide and look after the messy bits.
X  */
@@ -561,7 +566,8 @@
X 		/* fall through */
X 	case 0:
X 	call_kill:
-		kill_fasync(sock->fasync_list, SIGIO);
+		if(sock->fasync_list != NULL)
+			kill_fasync(sock->fasync_list, SIGIO);
X 		break;
X 	}
X 	return 0;
diff -u --recursive --new-file v2.3.3/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.3.3/linux/net/unix/af_unix.c	Fri May 14 18:55:33 1999
+++ linux/net/unix/af_unix.c	Wed May 26 18:14:38 1999
@@ -8,7 +8,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: af_unix.c,v 1.77 1999/05/12 11:25:07 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.78 1999/05/27 00:38:41 davem Exp $
X  *
X  * Fixes:
X  *		Linus Torvalds	:	Assorted bug cures.
@@ -144,19 +144,21 @@
X 	return (unix_peer(osk) == NULL || unix_our_peer(sk, osk));
X }
X 
+#define ulock(sk)	(&(sk->protinfo.af_unix.user_count))
+
X extern __inline__ void unix_lock(unix_socket *sk)
X {
-	atomic_inc(&sk->sock_readers);
+	atomic_inc(ulock(sk));
X }
X 
X extern __inline__ void unix_unlock(unix_socket *sk)
X {
-	atomic_dec(&sk->sock_readers);
+	atomic_dec(ulock(sk));
X }
X 
X extern __inline__ int unix_locked(unix_socket *sk)
X {
-	return atomic_read(&sk->sock_readers);
+	return (atomic_read(ulock(sk)) != 0);
X }
X 
X extern __inline__ void unix_release_addr(struct unix_address *addr)
@@ -1511,7 +1513,7 @@
X 	{
X 		len+=sprintf(buffer+len,"%p: %08X %08X %08lX %04X %02X %5ld",
X 			s,
-			atomic_read(&s->sock_readers),
+			atomic_read(ulock(s)),
X 			0,
X 			s->socket ? s->socket->flags : 0,
X 			s->type,
diff -u --recursive --new-file v2.3.3/linux/net/x25/af_x25.c linux/net/x25/af_x25.c
--- v2.3.3/linux/net/x25/af_x25.c	Thu Aug 27 19:33:09 1998
+++ linux/net/x25/af_x25.c	Tue May 25 13:06:35 1999
@@ -1336,14 +1336,20 @@
X 	/*
X 	 *	Register any pre existing devices.
X 	 */
-	for (dev = dev_base; dev != NULL; dev = dev->next)
+	read_lock_bh(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
X 		if ((dev->flags & IFF_UP) && (dev->type == ARPHRD_X25
X #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
X 					   || dev->type == ARPHRD_ETHER
X #endif
-									))
-		x25_link_device_up(dev);
-	
+			)) {
+			read_unlock_bh(&dev_base_lock);
+			x25_link_device_up(dev);
+			read_lock_bh(&dev_base_lock);
+		}
+	}
+	read_unlock_bh(&dev_base_lock);
+
X 	return 0;
X }
X 
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
echo 'File patch-2.3.4 is complete' &&
chmod 644 patch-2.3.4 ||
echo 'restore of patch-2.3.4 failed'
Cksum="`cksum < 'patch-2.3.4'`"
if ! test "3774889338 2855624" = "$Cksum"
then
	echo 'patch-2.3.4: original Checksum 3774889338 2855624, 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.'
#!/bin/sh
# this is part 48 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 48; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
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(0, __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(0, __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 }
@@ -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;
+	new->max_header_size = self->max_header_size;
+
X 	memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info));
X 
X 	/* Clean up the original one to keep it in listen state */
@@ -669,7 +703,7 @@
X 
X 	sock_init_data(sock, sk);
X 
-	sock->ops    = &irda_proto_ops;
+	sock->ops    = &irda_stream_ops;
X 	sk->protocol = protocol;
X 
X 	/* Register as a client with IrLMP */
@@ -786,12 +820,20 @@
X 			return -ENOTCONN;
X 	}
X 
-	skb = sock_alloc_send_skb(sk, len + IRDA_MAX_HEADER, 0, 
+	/* Check that we don't send out to big frames */
+	if (len > self->max_data_size) {
+		DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+		      "Chopping frame from %d to %d bytes!\n", len, 
+		      self->max_data_size);
+		len = self->max_data_size;
+	}
+
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
X 				  msg->msg_flags & MSG_DONTWAIT, &err);
X 	if (!skb)
X 		return -ENOBUFS;
X 
-	skb_reserve(skb, IRDA_MAX_HEADER);
+	skb_reserve(skb, self->max_header_size);
X 	
X 	DEBUG(4, __FUNCTION__ "(), appending user data\n");
X 	asmptr = skb->h.raw = skb_put(skb, len);
@@ -815,8 +857,8 @@
X  *    Try to receive message and copy it to user
X  *
X  */
-static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size,
-			int flags, struct scm_cookie *scm)
+static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, 
+			      int size, int flags, struct scm_cookie *scm)
X {
X 	struct irda_sock *self;
X 	struct sock *sk = sock->sk;
@@ -862,6 +904,161 @@
X }
X 
X /*
+ * Function irda_data_wait (sk)
+ *
+ *    Sleep until data has arrive. But check for races..
+ *
+ */
+static void irda_data_wait(struct sock *sk)
+{
+	if (!skb_peek(&sk->receive_queue)) {
+		sk->socket->flags |= SO_WAITDATA;
+		interruptible_sleep_on(sk->sleep);
+		sk->socket->flags &= ~SO_WAITDATA;
+	}
+}
+
+/*
+ * Function irda_recvmsg_stream (sock, msg, size, flags, scm)
+ *
+ *    
+ *
+ */
+static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg, 
+			       int size, int flags, struct scm_cookie *scm)
+{
+	struct irda_sock *self;
+	struct sock *sk = sock->sk;
+	int noblock = flags & MSG_DONTWAIT;
+	int copied = 0;
+	int target = 1;
+
+	DEBUG(3, __FUNCTION__ "()\n");
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	if (sock->flags & SO_ACCEPTCON) 
+		return(-EINVAL);
+
+	if (flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	if (flags & MSG_WAITALL)
+		target = size;
+		
+		
+	msg->msg_namelen = 0;
+
+	/* Lock the socket to prevent queue disordering
+	 * while sleeps in memcpy_tomsg
+	 */
+/* 	down(&self->readsem); */
+
+	do {
+		int chunk;
+		struct sk_buff *skb;
+
+		skb=skb_dequeue(&sk->receive_queue);
+		if (skb==NULL) {
+			if (copied >= target)
+				break;
+			
+			/*
+			 *	POSIX 1003.1g mandates this order.
+			 */
+			
+			if (sk->err) {
+				/* up(&self->readsem); */
+				return sock_error(sk);
+			}
+
+			if (sk->shutdown & RCV_SHUTDOWN)
+				break;
+
+		/* 	up(&self->readsem); */
+
+			if (noblock)
+				return -EAGAIN;
+			irda_data_wait(sk);
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+		/* 	down(&self->readsem); */
+			continue;
+		}
+
+		/* Never glue messages from different writers */
+/* 		if (check_creds && */
+/* 		    memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) */
+/* 		{ */
+/* 			skb_queue_head(&sk->receive_queue, skb); */
+/* 			break; */
+/* 		} */
+
+		chunk = min(skb->len, size);
+		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
+			skb_queue_head(&sk->receive_queue, skb);
+			if (copied == 0)
+				copied = -EFAULT;
+			break;
+		}
+		copied += chunk;
+		size -= chunk;
+
+ 		/* Copy credentials */
+/* 		scm->creds = *UNIXCREDS(skb); */
+/* 		check_creds = 1; */
+
+		/* Mark read part of skb as used */
+		if (!(flags & MSG_PEEK)) {
+			skb_pull(skb, chunk);
+
+/* 			if (UNIXCB(skb).fp) */
+/* 				unix_detach_fds(scm, skb); */
+
+			/* put the skb back if we didn't use it up.. */
+			if (skb->len) {
+				DEBUG(1, __FUNCTION__ "(), back on q!\n");
+				skb_queue_head(&sk->receive_queue, skb);
+				break;
+			}
+
+			kfree_skb(skb);
+			
+/* 			if (scm->fp) */
+/* 				break; */
+		} else {
+			DEBUG(0, __FUNCTION__ "() questionable!?\n");
+			/* It is questionable, see note in unix_dgram_recvmsg. */
+/* 			if (UNIXCB(skb).fp) */
+/* 				scm->fp = scm_fp_dup(UNIXCB(skb).fp); */
+
+			/* put message back and return */
+			skb_queue_head(&sk->receive_queue, skb);
+			break;
+		}
+	} while (size);
+
+	/*
+	 *  Check if we have previously stopped IrTTP and we know
+	 *  have more free space in our rx_queue. If so tell IrTTP
+	 *  to start delivering frames again before our rx_queue gets
+	 *  empty
+	 */
+	if (self->rx_flow == FLOW_STOP) {
+		if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
+			DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+			self->rx_flow = FLOW_START;
+			irttp_flow_request(self->tsap, FLOW_START);
+		}
+	}
+
+	/* up(&self->readsem); */
+
+	return copied;
+}
+
+/*
X  * Function irda_shutdown (sk, how)
X  *
X  *    
@@ -875,19 +1072,45 @@
X         return -EOPNOTSUPP;
X }
X 
-
X /*
X  * Function irda_poll (file, sock, wait)
X  *
X  *    
X  *
X  */
-unsigned int irda_poll(struct file *file, struct socket *sock, 
-		       struct poll_table_struct *wait)
+static unsigned int irda_poll(struct file * file, struct socket *sock, 
+			      poll_table *wait)
X {
-	DEBUG(0, __FUNCTION__ "()\n");
+	struct sock *sk = sock->sk;
+	unsigned int mask;
X 
-	return 0;
+	DEBUG(1, __FUNCTION__ "()\n");
+
+	poll_wait(file, sk->sleep, wait);
+	mask = 0;
+
+	/* exceptional events? */
+	if (sk->err)
+		mask |= POLLERR;
+	if (sk->shutdown & RCV_SHUTDOWN)
+		mask |= POLLHUP;
+
+	/* readable? */
+	if (!skb_queue_empty(&sk->receive_queue))
+		mask |= POLLIN | POLLRDNORM;
+
+	/* Connection-based need to check for termination and startup */
+	if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE)
+		mask |= POLLHUP;
+
+	/*
+	 * we set writable also when the other side has shut down the
+	 * connection. This prevents stuck sockets.
+	 */
+	if (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= MIN_WRITE_SPACE)
+			mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
+	return mask;
X }
X 
X /*
@@ -947,6 +1170,7 @@
X 		return -EINVAL;
X 		
X 	default:
+		DEBUG(0, __FUNCTION__ "(), doing device ioctl!\n");
X 		return dev_ioctl(cmd, (void *) arg);
X 	}
X 
@@ -1082,13 +1306,7 @@
X 			return -EFAULT;
X 		break;
X 	case IRTTP_MAX_SDU_SIZE:
-		if (self->max_sdu_size_tx != SAR_DISABLE)
-			val = self->max_sdu_size_tx;
-		else
-			/* SAR is disabled, so use the IrLAP data size
-			 * instead */
-			val = self->qos_tx.data_size.value - IRDA_MAX_HEADER;
-
+		val = self->max_data_size;
X 		DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
X 		len = sizeof(int);
X 		if (put_user(len, optlen))
@@ -1110,7 +1328,7 @@
X 	irda_create
X };
X 
-static struct proto_ops irda_proto_ops = {
+static struct proto_ops irda_stream_ops = {
X 	PF_IRDA,
X 	
X 	sock_no_dup,
@@ -1128,7 +1346,28 @@
X 	irda_getsockopt,
X 	sock_no_fcntl,
X 	irda_sendmsg,
-	irda_recvmsg
+	irda_recvmsg_stream
+};
+
+static struct proto_ops irda_dgram_ops = {
+	PF_IRDA,
+	
+	sock_no_dup,
+	irda_release,
+	irda_bind,
+	irda_connect,
+	sock_no_socketpair,
+	irda_accept,
+	irda_getname,
+	datagram_poll,
+	irda_ioctl,
+	irda_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	sock_no_fcntl,
+	irda_sendmsg,
+	irda_recvmsg_dgram
X };
X 
X /*
@@ -1215,7 +1454,7 @@
X 	irda_packet_type.type = htons(ETH_P_IRDA);
X         dev_remove_pack(&irda_packet_type);
X 
-        unregister_netdevice_notifier( &irda_dev_notifier);
+        unregister_netdevice_notifier(&irda_dev_notifier);
X 	
X 	sock_unregister(PF_IRDA);
X 	irda_cleanup();
diff -u --recursive --new-file v2.3.3/linux/net/irda/crc.c linux/net/irda/crc.c
--- v2.3.3/linux/net/irda/crc.c	Thu Dec 17 09:01:03 1998
+++ linux/net/irda/crc.c	Sun May 30 10:27:04 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Dec 12 09:56:35 1998
+ * Modified at:   Sun May  2 20:28:08 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       ppp.c by Michael Callahan <call...@maths.ox.ac.uk>
X  *                Al Longyear <long...@netcom.com>
@@ -59,7 +59,7 @@
X 
X unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len) 
X {
-    while ( len--)
-		fcs = IR_FCS(fcs, *buf++);
-    return fcs;
+	while (len--)
+                fcs = irda_fcs(fcs, *buf++);
+	return fcs;
X }
diff -u --recursive --new-file v2.3.3/linux/net/irda/discovery.c linux/net/irda/discovery.c
--- v2.3.3/linux/net/irda/discovery.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/discovery.c	Sun May 30 10:27:04 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Apr  6 15:33:50 1999
- * Modified at:   Sun Apr 11 00:41:58 1999
+ * Modified at:   Sun May  9 22:40:43 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -39,28 +39,51 @@
X /*
X  * Function irlmp_add_discovery (cachelog, discovery)
X  *
- *    
- *
+ *    Add a new discovery to the cachelog, and remove any old discoveries
+ *    from the same device
X  */
-void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery)
+void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
X {
-	discovery_t *old;
+	discovery_t *discovery, *node;
+	unsigned long flags;
+
+ spin_lock_irqsave(&irlmp->lock, flags);
X 
-	DEBUG(4, __FUNCTION__ "()\n");
+	/* 
+	 * Remove all discoveries of devices that has previously been 
+	 * discovered on the same link with the same name (info), or the 
+	 * same daddr. We do this since some devices (mostly PDAs) change
+	 * their device address between every discovery.
+	 */
+	discovery = (discovery_t *) hashbin_get_first(cachelog);
+	while (discovery != NULL ) {
+			node = discovery;
+
+			/* Be sure to stay one item ahead */
+			discovery = (discovery_t *) hashbin_get_next(cachelog);
+			
+			if ((node->daddr == new->daddr) || 
+			    (strcmp(node->info, new->info) == 0))
+			{
+				/* This discovery is a previous discovery 
+				 * from the same device, so just remove it
+				 */
+				hashbin_remove(cachelog, node->daddr, NULL);
+				kfree(node);
+			}
+		}
X 
-	/* Check if we have discovered this device before */
-	old = hashbin_remove(cachelog, discovery->daddr, NULL);
-	if (old)
-		kfree(old);
X 
X 	/* Insert the new and updated version */
-	hashbin_insert(cachelog, (QUEUE *) discovery, discovery->daddr, NULL);
+	hashbin_insert(cachelog, (QUEUE *) new, new->daddr, NULL);
+
+	spin_unlock_irqrestore(&irlmp->lock, flags);
X }
X 
X /*
X  * Function irlmp_add_discovery_log (cachelog, log)
X  *
- *    
+ *    Merge a disovery log into the cachlog.
X  *
X  */
X void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
diff -u --recursive --new-file v2.3.3/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.3.3/linux/net/irda/ircomm/ircomm_common.c	Thu May  6 16:40:53 1999
+++ linux/net/irda/ircomm/ircomm_common.c	Sun May 30 10:27:04 1999
@@ -8,7 +8,7 @@
X  * Author:        Takahide Higuchi <thig...@pluto.dti.ne.jp>
X  * Source:        irlpt_event.c
X  *
- *     Copyright (c) 1998, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
+ *     Copyright (c) 1998-1999, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
X  *     All Rights Reserved.
X  *
X  *     This program is free software; you can redistribute it and/or
@@ -44,18 +44,17 @@
X static char *revision_date = "Sun Apr 18 00:40:19 1999";
X 
X 
-static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb );
-
-static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event, 
+static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb );
+static void ircomm_state_discoverywait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
+				       struct sk_buff *skb );
+static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
+					IRCOMM_EVENT event, 
X 					struct sk_buff *skb );
-
-static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event, 
-					 struct sk_buff *skb );
-
-static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event, 
-					struct sk_buff *skb );
-
+static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
+				       struct sk_buff *skb );
X static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, 
X 				struct sk_buff *skb );
X static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, 
@@ -207,7 +206,7 @@
X 		ircomm[i]->ack_char = 0x06;  
X 
X 		ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE;   /* 64 */
-		ircomm[i]->maxsdusize = SAR_DISABLE;  
+		ircomm[i]->max_sdu_size = SAR_DISABLE;  
X 		ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
X 		if (ircomm[i]->ctrl_skb == NULL){
X 			DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
@@ -226,7 +225,6 @@
X 	create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
X #endif /* CONFIG_PROC_FS */
X 
-
X 	discovering_instance = NULL;
X 	return 0;
X }
@@ -275,51 +273,53 @@
X static int ircomm_accept_data_indication(void *instance, void *sap, 
X 					 struct sk_buff *skb)
X {
-	
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
X 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return -1;);
-	ASSERT( skb != NULL, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
X        
X 	DEBUG(4,__FUNCTION__"():\n");
-	ircomm_do_event( self, TTP_DATA_INDICATION, skb);
+	ircomm_do_event(self, TTP_DATA_INDICATION, skb);
X 	self->rx_packets++;
X 	
X 	return 0;
X }
X 
X static void ircomm_accept_connect_confirm(void *instance, void *sap,
-				   struct qos_info *qos, 
-				   __u32 maxsdusize, struct sk_buff *skb)
+					  struct qos_info *qos, 
+					  __u32 max_sdu_size, 
+					  __u8 max_header_size,
+					  struct sk_buff *skb)
X {
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
X 
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( qos != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
X 
X 	DEBUG(0,__FUNCTION__"(): got connected!\n");
X 
-	if(maxsdusize == SAR_DISABLE)
-		self->max_txbuff_size = qos->data_size.value; 
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_txbuff_size = qos->data_size.value - max_header_size;
X 	else {
-		ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;);
-		self->max_txbuff_size = maxsdusize; /* use fragmentation */
+		ASSERT(max_sdu_size >= COMM_DEFAULT_DATA_SIZE, return;);
+		self->max_txbuff_size = max_sdu_size; /* use fragmentation */
X 	}
X 
X 	self->qos = qos;
-	self->null_modem_mode = 0;            	/* disable null modem emulation */
+	self->max_header_size = max_header_size;
+	self->null_modem_mode = 0;         /* disable null modem emulation */
X 
-	ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb);
+	ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb);
X }
X 
X static void ircomm_accept_connect_indication(void *instance, void *sap,
-				      struct qos_info *qos,
-				      __u32 maxsdusize,
-				      struct sk_buff *skb )
+					     struct qos_info *qos,
+					     __u32 max_sdu_size,
+					     __u8 max_header_size,
+					     struct sk_buff *skb)
X {
X 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
X 
@@ -330,12 +330,14 @@
X 
X 	DEBUG(0,__FUNCTION__"()\n");
X 
-	if(maxsdusize == SAR_DISABLE)
-		self->max_txbuff_size = qos->data_size.value;
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_txbuff_size = qos->data_size.value - max_header_size;
X 	else
-		self->max_txbuff_size = maxsdusize;
+		self->max_txbuff_size = max_sdu_size;
X 
X 	self->qos = qos;
+	self->max_header_size = max_header_size;
+
X 	ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
X 
X 	/* stop connecting */
@@ -556,7 +558,7 @@
X 
X 		irttp_connect_request(self->tsap, self->dlsap, 
X 				      self->saddr, self->daddr, 
-				      NULL, self->maxsdusize, userdata); 
+				      NULL, self->max_sdu_size, userdata); 
X 		break;
X 
X 	default:
@@ -588,9 +590,9 @@
X /* 	if( !ircomm_parse_controlchannel( self, data)) */
X /* 		self->servicetype = DEFAULT;     TODOD:fix this! TH */
X 
-	if(self->notify.connect_indication)
+	if (self->notify.connect_indication)
X 		self->notify.connect_indication(self->notify.instance, self, 
-						qos, 0, skb);
+						qos, 0, 0, skb);
X }
X     
X #if 0
@@ -602,28 +604,26 @@
X #endif 
X 
X 
-static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
+static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb)
X {
X 	DEBUG(4 ,__FUNCTION__"()\n");
X 
X 	/* give a connect_confirm to the client */
X 	if( self->notify.connect_confirm )
X 		self->notify.connect_confirm(self->notify.instance,
-					     self, NULL, SAR_DISABLE, skb);
+					     self, NULL, SAR_DISABLE, 0, skb);
X }
X 
X static void issue_connect_response(struct ircomm_cb *self,
X 				   struct sk_buff *skb)
X {
-
X 	DEBUG(0,__FUNCTION__"()\n");
X 	
X 	if( self->servicetype == THREE_WIRE_RAW){
X 		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
X 		/* irlmp_connect_rsp(); */
-	} else {
-		irttp_connect_response(self->tsap, self->maxsdusize, skb);
-	}
+	} else
+		irttp_connect_response(self->tsap, self->max_sdu_size, skb);
X }
X 
X static void issue_disconnect_request(struct ircomm_cb *self,
@@ -642,30 +642,29 @@
X {
X 	int err;
X 
-	if(self->servicetype == THREE_WIRE_RAW){
+	if (self->servicetype == THREE_WIRE_RAW){
X 		/* irlmp_data_request(self->lmhandle,userdata); */
X 		DEBUG(0,__FUNCTION__"():not implemented!");
X 		return;
X 	}
X 
X 	DEBUG(4,__FUNCTION__"():sending frame\n");
-	err = irttp_data_request(self->tsap , userdata  );
-	if(err){
+	err = irttp_data_request(self->tsap, userdata);
+	if (err){
X 		printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n");
-		if(userdata)
+		if (userdata)
X 			dev_kfree_skb( userdata);
X 	}
X 	self->tx_packets++;
X }
X 
X static void issue_control_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata )
+				  struct sk_buff *userdata)
X {
X 	int err;
X 
X 	DEBUG(4,__FUNCTION__"()\n"); 
-	if(self->servicetype == THREE_WIRE_RAW)
-	{
+	if (self->servicetype == THREE_WIRE_RAW) {
X 		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
X 		
X 	}
@@ -676,7 +675,7 @@
X 		{
X 			printk( __FUNCTION__"():ttp_data_request failed\n");
X 			if(userdata)
-				dev_kfree_skb( userdata);
+				dev_kfree_skb(userdata);
X 		}
X 		else
X 			self->tx_controls++;
@@ -701,7 +700,7 @@
X 
X  	/* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */
X 
-	if(self->notify.data_indication && skb->len)
+	if (self->notify.data_indication && skb->len)
X 		self->notify.data_indication(self->notify.instance, self,
X 					     skb);
X }
@@ -728,7 +727,7 @@
X 	
X 	DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n",
X 	       ircommstate[self->state], ircommevent[event]);
-	(*state[ self->state ]) ( self, event, skb);
+	(*state[self->state])(self, event, skb);
X }
X 
X static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
@@ -747,7 +746,7 @@
X static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
X 			       struct sk_buff *skb )
X {
-	switch(event){
+	switch (event){
X 	case IRCOMM_CONNECT_REQUEST:
X 
X 		/* ircomm_next_state(self, COMM_WAITI); */
@@ -779,7 +778,8 @@
X /*
X  * ircomm_state_discoverywait
X  */
-static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static void ircomm_state_discoverywait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
X 				       struct sk_buff *skb )
X {
X 	switch(event){
@@ -817,11 +817,11 @@
X  * ircomm_state_queryparamwait
X  */
X 
-static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event, 
-					struct sk_buff *skb )
+static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
+					IRCOMM_EVENT event, 
+					struct sk_buff *skb)
X {
-	switch(event){
-
+	switch (event) {
X 	case TTP_CONNECT_INDICATION:
X 
X 		ircomm_next_state(self, COMM_WAITR);
@@ -855,10 +855,11 @@
X  * ircomm_state_querylsapwait
X  */
X 
-static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
X 				       struct sk_buff *skb )
X {
-	switch(event){
+	switch (event) {
X 
X 	case TTP_CONNECT_INDICATION:
X 
@@ -898,10 +899,10 @@
X static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
X 			  struct sk_buff *skb )
X {
-	switch(event){
+	switch (event) {
X 	case TTP_CONNECT_CONFIRM:
X 		ircomm_next_state(self, COMM_CONN);
-		connect_confirmation( self, skb );
+		connect_confirm(self, skb );
X 		break;
X 	case TTP_DISCONNECT_INDICATION:
X 		ircomm_next_state(self, COMM_IDLE);
@@ -921,21 +922,18 @@
X 	}
X }
X 
-
-
X /*
X  * ircomm_state_waitr
X  */
X static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ) 
+			       struct sk_buff *skb ) 
X {
-	
-	switch(event){
+	switch (event) {
X 	case IRCOMM_CONNECT_RESPONSE:
X 
X 	        /* issue_connect_response */
X 		
-		if(self->servicetype==THREE_WIRE_RAW){
+		if (self->servicetype==THREE_WIRE_RAW) {
X 			DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n");
X 			/* irlmp_connect_response(Vpeersap,
X 			 *                         ACCEPT,null);
@@ -987,7 +985,7 @@
X static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
X 			      struct sk_buff *skb )
X {
-	switch(event){
+	switch (event) {
X 	case TTP_DATA_INDICATION:
X 		process_data(self, skb);
X 		break;
@@ -1033,8 +1031,6 @@
X 	}
X }
X 
-
-
X /*
X  *  ----------------------------------------------------------------------
X  *  IrCOMM service interfaces and supporting functions
@@ -1042,12 +1038,12 @@
X  *  ----------------------------------------------------------------------
X  */
X 
-/* 
- * start_discovering()
+/*
+ * Function start_discovering (self)
+ *
+ *    Start discovering and enter DISCOVERY_WAIT state
X  *
- * start discovering and enter DISCOVERY_WAIT state
X  */
-
X static void start_discovering(struct ircomm_cb *self)
X {
X 	__u16  hints; 
@@ -1092,19 +1088,26 @@
X /*
X  * queryias_done(self)
X  *
- * called when discovery process got wrong results, completed, or terminated.
+ * 
X  */
X 
+/*
+ * Function queryias_done (self)
+ *
+ *    Called when discovery process got wrong results, completed, or
+ *    terminated.
+ * 
+ */
X static void queryias_done(struct ircomm_cb *self)
X {
X 	DEBUG(0, __FUNCTION__"():\n");
-	if(self->queryias_lock){
+	if (self->queryias_lock){
X 		self->queryias_lock = 0;
X 		discovering_instance = NULL;
X 		MOD_DEC_USE_COUNT;
X 		irlmp_unregister_client(self->ckey);
X 	}
-	if(ircomm_cs != 1)
+	if (ircomm_cs != 1)
X 		irlmp_unregister_service(self->skey);
X 	return;
X }
@@ -1120,7 +1123,6 @@
X 				       ircomm_getvalue_confirm, self );
X }
X 
-
X static void query_lsapsel(struct ircomm_cb * self)
X {
X 	DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n");
@@ -1135,13 +1137,13 @@
X 	}
X }
X 
-/* 
- * ircomm_connect_request()
- * Impl. of this function is differ from one of the reference.
- * This functin does discovery as well as sending connect request
+/*
+ * Function ircomm_connect_request (self, servicetype)
+ *
+ *    Impl. of this function is differ from one of the reference. This
+ *    function does discovery as well as sending connect request
+ * 
X  */
-
-
X void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype)
X {
X 	/*
@@ -1158,12 +1160,12 @@
X 	self->servicetype= servicetype;
X 	/* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/
X 
-	self->maxsdusize = SAR_DISABLE;
-	ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL);
+	self->max_sdu_size = SAR_DISABLE;
+	ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL);
X }
X 
X void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     __u32 maxsdusize)
+			     __u32 max_sdu_size)
X {
X 
X 	ASSERT( self != NULL, return;);
@@ -1177,10 +1179,11 @@
X 	 * and send it with connect_response
X 	 */
X 
-	if(!userdata){
+	if (!userdata){
X 		/* FIXME: check for errors and initialize? DB */
X 		userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
-		ASSERT(userdata != NULL, return;);
+		if (userdata == NULL)
+			return;
X 
X 		skb_reserve(userdata,COMM_HEADER_SIZE);
X 	}
@@ -1188,9 +1191,10 @@
X 	/* enable null-modem emulation (i.e. server mode )*/
X 	self->null_modem_mode = 1;
X 
-	self->maxsdusize = maxsdusize;
-	if(maxsdusize != SAR_DISABLE)
-		self->max_txbuff_size = maxsdusize;
+	self->max_sdu_size = max_sdu_size;
+	if (max_sdu_size != SAR_DISABLE)
+		self->max_txbuff_size = max_sdu_size;
+
X 	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
X }	
X 
@@ -1341,14 +1345,13 @@
X 	self->control_ch_pending = 1;
X }
X 
-
-
X /*
- * ircomm_control_request();
- * this function is exported as a request to send some control-channel tuples
- * to peer device
+ * Function ircomm_control_request (self, instruction)
+ *
+ *    This function is exported as a request to send some control-channel
+ *    tuples * to peer device
+ * 
X  */
-
X void ircomm_control_request(struct ircomm_cb *self,  __u8 instruction)
X {
X 
diff -u --recursive --new-file v2.3.3/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c
--- v2.3.3/linux/net/irda/ircomm/irvtd_driver.c	Fri May 14 18:55:32 1999
+++ linux/net/irda/ircomm/irvtd_driver.c	Sun May 30 10:27:04 1999
@@ -8,7 +8,7 @@
X  * Source:        serial.c by Linus Torvalds
X  *                isdn_tty.c by Fritz Elfert
X  *
- *     Copyright (c) 1998, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
+ *     Copyright (c) 1998-1999, Takahide Higuchi, <thig...@pluto.dti.ne.jp>,
X  *     All Rights Reserved.
X  *
X  *     This program is free software; you can redistribute it and/or
@@ -341,15 +341,15 @@
X  ***********************************************************************
X  */
X 
-
X /*
X  * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb)
X  *
- *    ircomm_connect_request which we have send have succeed!
+ *    ircomm_connect_request which we have send, has succeeded!
X  *
X  */
X void irvtd_connect_confirm(void *instance, void *sap, 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 irvtd_cb *driver = (struct irvtd_cb *)instance;
X 	ASSERT(driver != NULL, return;);
@@ -364,7 +364,7 @@
X 	/*
X 	 * sending initial control parameters here
X 	 */
-	if(driver->comm->servicetype ==	THREE_WIRE_RAW)
+	if (driver->comm->servicetype ==	THREE_WIRE_RAW)
X 		return;                /* do nothing */
X 
X 	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
@@ -376,7 +376,7 @@
X 	ircomm_control_request(driver->comm, XON_XOFF_CHAR);
X 	/* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */
X 
-	switch(driver->comm->servicetype){
+	switch (driver->comm->servicetype) {
X 	case CENTRONICS:
X 		break;
X 
@@ -397,17 +397,18 @@
X  *
X  */
X void irvtd_connect_indication(void *instance, void *sap, 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 irvtd_cb *driver = (struct irvtd_cb *)instance;
X 	struct ircomm_cb *comm = (struct ircomm_cb *)sap;
+
X 	ASSERT(driver != NULL, return;);
X 	ASSERT(driver->magic == IRVTD_MAGIC, return;);
X 	ASSERT(comm != NULL, return;);
X 	ASSERT(comm->magic == IRCOMM_MAGIC, return;);
X 
-	DEBUG(4,"irvtd_connect_indication:sending connect_response...\n");
+	DEBUG(4, __FUNCTION__ "():sending connect_response...\n");
X 
X 	ircomm_connect_response(comm, NULL, SAR_DISABLE );
X 
@@ -416,7 +417,7 @@
X 	/*
X 	 * send initial control parameters
X 	 */
-	if(driver->comm->servicetype ==	THREE_WIRE_RAW)
+	if (driver->comm->servicetype == THREE_WIRE_RAW)
X 		return;                /* do nothing */
X 
X 	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
@@ -426,6 +427,7 @@
X 		ircomm_control_request(driver->comm, DTELINE_STATE);
X 		break;
X 	default:
+		DEBUG(0, __FUNCTION__ "(), not implemented!\n");
X 	}
X 
X 
@@ -576,6 +578,7 @@
X 	case DATA_RATE:
X 	case XON_XOFF_CHAR:
X 	case DTELINE_STATE:
+	case ENQ_ACK_CHAR:	/* got this from win95 */
X 		/* (maybe) nothing to do  */
X 		break;
X 	default:
@@ -778,7 +781,7 @@
X 	skb_queue_head_init(&driver->rxbuff);
X 	driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); 
X 	if (!driver->txbuff){
-		DEBUG(0,__FUNCTION__"():alloc_skb failed!\n");
+		DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n");
X 		return -ENOMEM;
X 	}
X 	skb_reserve(driver->txbuff, COMM_HEADER_SIZE);
@@ -793,9 +796,8 @@
X 	irvtd_notify.instance = driver;
X 
X 	driver->comm = ircomm_open_instance(irvtd_notify);
-	if(!driver->comm){
+	if (!driver->comm)
X 		return -ENODEV;
-	}
X 
X 
X 	/* 
diff -u --recursive --new-file v2.3.3/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.3/linux/net/irda/irda_device.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irda_device.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Wed Apr 21 09:48:19 1999
+ * Modified at:   Mon May 10 23:02:47 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 
@@ -31,6 +31,8 @@
X #include <linux/netdevice.h>
X #include <linux/init.h>
X #include <linux/tty.h>
+#include <linux/kmod.h>
+#include <linux/wireless.h>
X 
X #include <asm/ioctls.h>
X #include <asm/segment.h>
@@ -53,7 +55,8 @@
X extern int actisys_init(void);
X extern int girbil_init(void);
X 
-hashbin_t *irda_device = NULL;
+static hashbin_t *irda_device = NULL;
+static hashbin_t *dongles = NULL;
X 
X /* Netdevice functions */
X static int irda_device_net_rebuild_header(struct sk_buff *skb);
@@ -61,9 +64,9 @@
X 				       struct device *dev,
X 				       unsigned short type, void *daddr, 
X 				       void *saddr, unsigned len);
-static int irda_device_net_set_config( struct device *dev, struct ifmap *map);
-static int irda_device_net_change_mtu( struct device *dev, int new_mtu);
-
+static int irda_device_net_set_config(struct device *dev, struct ifmap *map);
+static int irda_device_net_change_mtu(struct device *dev, int new_mtu);
+static int irda_device_net_ioctl(struct device *dev, struct ifreq *rq,int cmd);
X #ifdef CONFIG_PROC_FS
X int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
X 			   int unused);
@@ -74,8 +77,15 @@
X {
X 	/* Allocate master array */
X 	irda_device = hashbin_new( HB_LOCAL);
-	if ( irda_device == NULL) {
-		printk( KERN_WARNING "IrDA: Can't allocate irda_device hashbin!\n");
+	if (irda_device == NULL) {
+		WARNING("IrDA: Can't allocate irda_device hashbin!\n");
+		return -ENOMEM;
+	}
+
+	dongles = hashbin_new(HB_LOCAL);
+	if (dongles == NULL) {
+		printk(KERN_WARNING 
+		       "IrDA: Can't allocate dongles hashbin!\n");
X 		return -ENOMEM;
X 	}
X 
@@ -113,6 +123,7 @@
X 
X 	ASSERT(irda_device != NULL, return;);
X 
+	hashbin_delete(dongles, NULL);
X 	hashbin_delete(irda_device, (FREE_FUNC) irda_device_close);
X }
X 
@@ -238,7 +249,7 @@
X /*
X  * Function irda_device_close (self)
X  *
- *    
+ *    Close the device
X  *
X  */
X void irda_device_close(struct irda_device *self)
@@ -248,6 +259,10 @@
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
X 
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		self->dongle->close(self);
+
X 	/* Stop and remove instance of IrLAP */
X 	if (self->irlap)
X 		irlap_close(self->irlap);
@@ -298,15 +313,19 @@
X 	 */
X 	if (self->wait_until_sent) {
X 		self->wait_until_sent(self);
+		
+		if (self->dongle)
+			self->dongle->change_speed(self, speed);
+		
X 		if (self->change_speed) {
X 			self->change_speed(self, speed);
-
+			
X 			/* Update the QoS value only */
X 			self->qos.baud_rate.value = speed;
X 		}
X 	} else {
-		printk(KERN_WARNING "wait_until_sent() "
-		       "has not implemented by the IrDA device driver!\n");
+		WARNING("IrDA: wait_until_sent() "
+			"has not implemented by the IrDA device driver!\n");
X 	}
X }
X 
@@ -386,6 +405,7 @@
X 	dev->set_config      = irda_device_net_set_config;
X 	dev->change_mtu      = irda_device_net_change_mtu;
X /*  	dev->hard_header     = irda_device_net_hard_header; */
+	dev->do_ioctl        = irda_device_net_ioctl;
X         dev->hard_header_len = 0;
X         dev->addr_len        = 0;
X 
@@ -444,6 +464,125 @@
X      return 0;  
X }
X 
+static int irda_device_net_ioctl(struct device *dev, /* ioctl device */
+				 struct ifreq *rq,   /* Data passed */
+				 int	cmd)	     /* Ioctl number */
+{
+	unsigned long flags;
+	int			ret = 0;
+#ifdef WIRELESS_EXT
+	struct iwreq *wrq = (struct iwreq *) rq;
+#endif
+	struct irda_device *self;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = (struct irda_device *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	/* Look what is the request */
+	switch (cmd) {
+#ifdef WIRELESS_EXT
+	case SIOCGIWNAME:
+		/* Get name */
+		strcpy(wrq->u.name, self->name);
+		break;
+	case SIOCSIWNWID:
+		/* Set domain */
+		if (wrq->u.nwid.on) {
+			
+		} break;
+	case SIOCGIWNWID:
+		/* Read domain*/
+/* 		wrq->u.nwid.nwid = domain; */
+/* 		wrq->u.nwid.on = 1; */
+		break;
+	case SIOCGIWENCODE:
+		/* Get scramble key */
+		/* 	wrq->u.encoding.code = scramble_key; */
+/* 		wrq->u.encoding.method = 1; */
+		break;
+	case SIOCSIWENCODE:
+		/* Set  scramble key */
+		/* scramble_key = wrq->u.encoding.code; */
+		break;
+	case SIOCGIWRANGE:
+		/* Basic checking... */
+		if(wrq->u.data.pointer != (caddr_t) 0) {
+			struct iw_range	range;
+			
+			/* Verify the user buffer */
+			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
+					  sizeof(struct iw_range));
+			if(ret)
+				break;
+			
+			/* Set the length (useless : its constant...) */
+			wrq->u.data.length = sizeof(struct iw_range);
+			
+			/* Set information in the range struct */
+			range.throughput = 1.6 * 1024 * 1024;	/* don't argue on this ! */
+			range.min_nwid = 0x0000;
+			range.max_nwid = 0x01FF;
+			
+			range.num_channels = range.num_frequency = 0;
+			
+			range.sensitivity = 0x3F;
+			range.max_qual.qual = 255;
+			range.max_qual.level = 255;
+			range.max_qual.noise = 0;
+			
+			/* Copy structure to the user buffer */
+			copy_to_user(wrq->u.data.pointer, &range,
+				     sizeof(struct iw_range));
+		}
+		break;
+	case SIOCGIWPRIV:
+		/* Basic checking... */
+#if 0
+		if (wrq->u.data.pointer != (caddr_t) 0) {
+			struct iw_priv_args	priv[] =
+			{	/* cmd,		set_args,	get_args,	name */
+				{ SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, 
+				  sizeof(struct site_survey), 
+				  "getsitesurvey" },
+			};
+			
+			/* Verify the user buffer */
+			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
+					  sizeof(priv));
+			if (ret)
+				break;
+			
+			/* Set the number of ioctl available */
+			wrq->u.data.length = 1;
+			
+			/* Copy structure to the user buffer */
+			copy_to_user(wrq->u.data.pointer, (u_char *) priv,
+				     sizeof(priv));
+		}
+#endif 
+		break;
+#endif
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
X /*
X  * Function irda_device_transmit_finished (void)
X  *
@@ -451,7 +590,7 @@
X  *    device. Maybe we should use: q->q.qlen == 0.
X  *
X  */
-int irda_device_txqueue_empty( struct irda_device *self)
+int irda_device_txqueue_empty(struct irda_device *self)
X {
X 	ASSERT(self != NULL, return -1;);
X 	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);	
@@ -463,6 +602,117 @@
X }
X 
X /*
+ * Function irda_device_init_dongle (self, type)
+ *
+ *    Initialize attached dongle. Warning, must be called with a process
+ *    context!
+ */
+void irda_device_init_dongle(struct irda_device *self, int type)
+{
+	struct dongle_q *node;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+
+#ifdef CONFIG_KMOD
+	/* Try to load the module needed */
+	switch (type) {
+	case ESI_DONGLE:
+		MESSAGE("IrDA: Initializing ESI dongle!\n");
+		request_module("esi");
+		break;
+	case TEKRAM_DONGLE:
+		MESSAGE("IrDA: Initializing Tekram dongle!\n");
+		request_module("tekram");
+		break;
+	case ACTISYS_DONGLE:     /* FALLTHROUGH */
+	case ACTISYS_PLUS_DONGLE:
+		MESSAGE("IrDA: Initializing ACTiSYS dongle!\n");
+		request_module("actisys");
+		break;
+	case GIRBIL_DONGLE:
+		MESSAGE("IrDA: Initializing GIrBIL dongle!\n");
+		request_module("girbil");
+		break;
+	case LITELINK_DONGLE:
+		MESSAGE("IrDA: Initializing Litelink dongle!\n");
+		request_module("litelink");
+		break;
+	default:
+		ERROR("Unknown dongle type!\n");
+		return;
+	}
+#endif /* CONFIG_KMOD */
+
+	node = hashbin_find(dongles, type, NULL);
+	if (!node) {
+		ERROR("IrDA: Unable to find requested dongle\n");
+		return;
+	}
+
+	/* Set the dongle to be used by this driver */
+	self->dongle = node->dongle;
+
+	/* Now initialize the dongle!  */
+	node->dongle->open(self, type);
+	node->dongle->qos_init(self, &self->qos);
+	
+	/* Reset dongle */
+	node->dongle->reset(self, 0);
+
+	/* Set to default baudrate */
+	irda_device_change_speed(self, 9600);
+}
+
+/*
+ * Function irda_device_register_dongle (dongle)
+ *
+ *    
+ *
+ */
+int irda_device_register_dongle(struct dongle *dongle)
+{
+	struct dongle_q *new;
+	
+	/* Check if this dongle has been registred before */
+	if (hashbin_find(dongles, dongle->type, NULL)) {
+		MESSAGE(__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;
+}
+
+/*
+ * Function irda_device_unregister_dongle (dongle)
+ *
+ *    
+ *
+ */
+void irda_device_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  * Function setup_dma (idev, buffer, count, mode)
X  *
X  *    Setup the DMA channel
@@ -536,7 +786,7 @@
X 
X 	self = (struct irda_device *) hashbin_get_first(irda_device);
X 	while ( self != NULL) {
-		len += sprintf(buf+len, "%s,", self->name);
+		len += sprintf(buf+len, "\n%s,", self->name);
X 		len += sprintf(buf+len, "\tbinding: %s\n", 
X 			       self->description);
X 		
diff -u --recursive --new-file v2.3.3/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.3.3/linux/net/irda/iriap.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/iriap.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Fri Apr 23 09:57:12 1999
+ * Modified at:   Sun May  9 15:59:05 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 
@@ -62,12 +62,17 @@
X extern char *lmp_reasons[];
X 
X static struct iriap_cb *iriap_open( __u8 slsap, int mode);
-static void __iriap_close( struct iriap_cb *self);
+static void __iriap_close(struct iriap_cb *self);
X static void iriap_disconnect_indication(void *instance, void *sap, 
X 					LM_REASON reason, struct sk_buff *skb);
X static void iriap_connect_indication(void *instance, void *sap, 
X 				     struct qos_info *qos, __u32 max_sdu_size,
+				     __u8 max_header_size, 
X 				     struct sk_buff *skb);
+static void iriap_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos, 
+				  __u32 max_sdu_size, __u8 max_header_size,
+				  struct sk_buff *skb);
X static int iriap_data_indication(void *instance, void *sap, 
X 				 struct sk_buff *skb);
X 
@@ -181,7 +186,7 @@
X 	self->slsap_sel = slsap_sel;
X 	self->mode = mode;
X 
-	init_timer( &self->watchdog_timer);
+	init_timer(&self->watchdog_timer);
X 
X 	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
X 	
@@ -206,7 +211,7 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IAS_MAGIC, return;);
X 
-	del_timer( &self->watchdog_timer);
+	del_timer(&self->watchdog_timer);
X 
X 	self->magic = 0;
X 
@@ -260,7 +265,7 @@
X 
X 	ASSERT( iriap != NULL, return;);
X 
-	del_timer( &self->watchdog_timer);
+	del_timer(&self->watchdog_timer);
X 
X 	if ( self->mode == IAS_CLIENT) {
X 		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
@@ -284,9 +289,8 @@
X 				       NULL);
X 	}
X 
-	if ( userdata) {
+	if (userdata)
X 		dev_kfree_skb( userdata);
-	}
X }
X 
X /*
@@ -295,28 +299,28 @@
X  *    
X  *
X  */
-void iriap_disconnect_request( struct iriap_cb *self)
+void iriap_disconnect_request(struct iriap_cb *self)
X {
X 	struct sk_buff *skb;
X 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
X 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
X 
-	skb = dev_alloc_skb( 64);
+	skb = dev_alloc_skb(64);
X 	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an sk_buff of length %d\n", 64);
+		DEBUG(0, __FUNCTION__
+		      "(), Could not allocate an sk_buff of length %d\n", 64);
X 		return;
X 	}
X 
X 	/* 
-	 *  Reserve space for MUX and LAP header 
+	 *  Reserve space for MUX control and LAP header 
X 	 */
- 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+ 	skb_reserve(skb, LMP_MAX_HEADER);
X 
-	irlmp_disconnect_request( self->lsap, skb);
+	irlmp_disconnect_request(self->lsap, skb);
X }
X 
X void iriap_getinfobasedetails_request(void) 
@@ -381,7 +385,7 @@
X 	/* Give ourselves 10 secs to finish this operation */
X 	iriap_start_watchdog_timer(self, 10*HZ);
X 	
-	skb = dev_alloc_skb( 64);
+	skb = dev_alloc_skb(64);
X 	if (!skb)
X 		return;
X 
@@ -389,7 +393,7 @@
X 	attr_len = strlen(attr);
X 
X 	/* Reserve space for MUX and LAP header */
- 	skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+ 	skb_reserve(skb, self->max_header_size);
X 	skb_put(skb, 3+name_len+attr_len);
X 	frame = skb->data;
X 
@@ -535,13 +539,13 @@
X 	 *  value. We add 9 bytes because of the 6 bytes for the frame and
X 	 *  max 3 bytes for the value coding.
X 	 */
-	skb = dev_alloc_skb(value->len + LMP_HEADER + LAP_HEADER + 9);
+	skb = dev_alloc_skb(value->len + self->max_header_size + 9);
X 	if (!skb)
X 		return;
X 
X 	/* Reserve space for MUX and LAP header */
- 	skb_reserve( skb, LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 6);
+ 	skb_reserve(skb, self->max_header_size);
+	skb_put(skb, 6);
X 	
X 	fp = skb->data;
X 
@@ -666,7 +670,7 @@
X /*
X  * Function iriap_send_ack (void)
X  *
- *    
+ *    Currently not used
X  *
X  */
X void iriap_send_ack( struct iriap_cb *self) 
@@ -679,13 +683,13 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IAS_MAGIC, return;);
X 
-	skb = dev_alloc_skb( 64);
+	skb = dev_alloc_skb(64);
X 	if (!skb)
X 		return;
X 
X 	/* Reserve space for MUX and LAP header */
- 	skb_reserve( skb, 4);
-	skb_put( skb, 3);
+ 	skb_reserve(skb, self->max_header_size);
+	skb_put(skb, 1);
X 	frame = skb->data;
X 
X 	/* Build frame */
@@ -698,8 +702,10 @@
X  *    LSAP connection confirmed!
X  *
X  */
-void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *userdata)
+static void iriap_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos, 
+				  __u32 max_sdu_size, __u8 header_size, 
+				  struct sk_buff *userdata)
X {
X 	struct iriap_cb *self;
X 	
@@ -711,7 +717,7 @@
X 	
X 	DEBUG(4, __FUNCTION__ "()\n");
X 	
-	/* del_timer( &self->watchdog_timer); */
+	del_timer(&self->watchdog_timer);
X 
X 	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
X }
@@ -724,19 +730,17 @@
X  */
X static void iriap_connect_indication(void *instance, void *sap, 
X 				     struct qos_info *qos, __u32 max_sdu_size,
+				     __u8 header_size, 
X 				     struct sk_buff *userdata)
X {
X 	struct iriap_cb *self;
X 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = ( struct iriap_cb *) instance;
+	self = (struct iriap_cb *) instance;
X 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( self->mode == IAS_SERVER, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
X 
-	iriap_do_server_event( self, IAP_LM_CONNECT_INDICATION, userdata);
+	iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
X }
X  
X /*
@@ -856,7 +860,7 @@
X 	}
X 	opcode &= 0x7f; /* Mask away LST bit */
X 	
-	switch( opcode) {
+	switch (opcode) {
X 	case GET_INFO_BASE:
X 		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
X 		break;
diff -u --recursive --new-file v2.3.3/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c
--- v2.3.3/linux/net/irda/iriap_event.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/iriap_event.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Tue Jan 26 12:29:36 1999
+ * Modified at:   Sun May  9 11:01:47 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 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 
@@ -387,9 +387,9 @@
X 		}
X 
X 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve( tx_skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(tx_skb, LMP_MAX_HEADER);
X 		
-		irlmp_connect_response( self->lsap, tx_skb);
+		irlmp_connect_response(self->lsap, tx_skb);
X 		/*LM_Idle_request(idle); */
X 		
X 		iriap_next_server_state( self, R_CALL);
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c
--- v2.3.3/linux/net/irda/irlan/irlan_client.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlan/irlan_client.c	Sun May 30 10:27:04 1999
@@ -6,13 +6,14 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 23:03:55 1999
+ * Modified at:   Tue May 11 00:22:39 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       skeleton.c by Donald Becker <bec...@CESDIS.gsfc.nasa.gov>
X  *                slip.c by Laurence Culhane, <l...@holmes.demon.co.uk>
X  *                          Fred N. van Kempen, <wal...@uwalt.nl.mugnet.org>
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 
@@ -61,6 +62,7 @@
X static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
X 					      struct qos_info *qos, 
X 					      __u32 max_sdu_size,
+					      __u8 max_header_size,
X 					      struct sk_buff *);
X static void irlan_check_response_param(struct irlan_cb *self, char *param, 
X 				       char *value, int val_len);
@@ -79,7 +81,7 @@
X 	 * indication it needs to make progress. If the client is still in 
X 	 * IDLE state, we must kick it to, but only if the provider is not IDLE
X  	 */
-	if ((self->access_type == ACCESS_PEER) && 
+	if ((self->provider.access_type == ACCESS_PEER) && 
X 	    (self->client.state == IRLAN_IDLE) &&
X 	    (self->provider.state != IRLAN_IDLE)) {
X 		irlan_client_wakeup(self, self->saddr, self->daddr);
@@ -105,23 +107,29 @@
X {
X 	struct irmanager_event mgr_event;
X 
-	DEBUG(0, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
X 
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 
-	/* Check if we are already awake */
-	if (self->client.state != IRLAN_IDLE)
+	/* 
+	 * Check if we are already awake, or if we are a provider in direct
+	 * mode (in that case we must leave the client idle
+	 */
+	if ((self->client.state != IRLAN_IDLE) || 
+	    (self->provider.access_type == ACCESS_DIRECT))
X 		return;
X 
X 	/* saddr may have changed! */
X 	self->saddr = saddr;
X 	
-	/* Check if network device is up */
+	/* Before we try to connect, we check if network device is up. If it
+	 * is up, that means that the "user" really wants to connect. If not
+	 * we notify the user about the possibility of an IrLAN connection
+	 */
X 	if (self->dev.start) {
X 		/* Open TSAPs */
X 		irlan_client_open_ctrl_tsap(self);
- 		irlan_provider_open_ctrl_tsap(self);
X  		irlan_open_data_tsap(self);
X 		
X 		irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
@@ -161,7 +169,7 @@
X 	struct irlan_cb *self, *entry;
X 	__u32 saddr, daddr;
X 	
-	DEBUG(0, __FUNCTION__"()\n");
+	DEBUG(1, __FUNCTION__"()\n");
X 
X 	ASSERT(irlan != NULL, return;);
X 	ASSERT(discovery != NULL, return;);
@@ -176,7 +184,8 @@
X       	if (self) {
X 		ASSERT(self->magic == IRLAN_MAGIC, return;);
X 
-		DEBUG(2, __FUNCTION__ "(), Found instance!\n");
+		DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n",
+		      daddr);
X 		
X 		irlan_client_wakeup(self, saddr, daddr);
X 
@@ -184,30 +193,13 @@
X 	}
X 	
X 	/* 
-	 * We have no instance for daddr, so try and find an unused one
+	 * We have no instance for daddr, so start a new one
X 	 */
-	self = hashbin_find(irlan, DEV_ADDR_ANY, NULL);
-	if (self) {
-		DEBUG(0, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n");
-		/*
-		 * Rehash instance, now we have a client (daddr) to serve.
-		 */
-		entry = hashbin_remove(irlan, self->daddr, NULL);
-		ASSERT(entry == self, return;);
-
-		self->daddr = daddr;
-		self->saddr = saddr;
+	DEBUG(1, __FUNCTION__ "(), starting new instance!\n");
+	self = irlan_open(saddr, daddr, TRUE);
X 
-		DEBUG(0, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
-		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
-		
-		/* Check if network device has been registered */
-		if (!self->netdev_registered)
-			irlan_register_netdev(self);
-		
-		/* Restart watchdog timer */
-		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
-	}
+	/* Restart watchdog timer */
+	irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
X }
X 	
X /*
@@ -302,6 +294,7 @@
X static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
X 					      struct qos_info *qos, 
X 					      __u32 max_sdu_size,
+					      __u8 max_header_size,
X 					      struct sk_buff *skb) 
X {
X 	struct irlan_cb *self;
@@ -313,6 +306,9 @@
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 
+	self->client.max_sdu_size = max_sdu_size;
+	self->client.max_header_size = max_header_size;
+
X 	/* TODO: we could set the MTU depending on the max_sdu_size */
X 
X 	irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
@@ -339,7 +335,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -410,11 +406,11 @@
X 	/* For all parameters */
X  	for (i=0; i<count;i++) {
X 		ret = irlan_extract_param(ptr, name, value, &val_len);
-		if (ret == -1) {
+		if (ret < 0) {
X 			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
X 			break;
X 		}
-		ptr+=ret;
+		ptr += ret;
X 		irlan_check_response_param(self, name, value, val_len);
X  	}
X 	/* Cleanup */
@@ -423,9 +419,9 @@
X }
X 
X /*
- * Function check_param (param, value)
+ * Function irlan_check_response_param (self, param, value, val_len)
X  *
- *    Check which parameter is received and update local variables
+ *     Check which parameter is received and update local variables
X  *
X  */
X static void irlan_check_response_param(struct irlan_cb *self, char *param, 
@@ -469,11 +465,11 @@
X 	}
X 	if (strcmp(param, "ACCESS_TYPE") == 0) {
X 		if (strcmp(value, "DIRECT") == 0)
-			self->access_type = ACCESS_DIRECT;
+			self->client.access_type = ACCESS_DIRECT;
X 		else if (strcmp(value, "PEER") == 0)
-			self->access_type = ACCESS_PEER;
+			self->client.access_type = ACCESS_PEER;
X 		else if (strcmp(value, "HOSTED") == 0)
-			self->access_type = ACCESS_HOSTED;
+			self->client.access_type = ACCESS_HOSTED;
X 		else {
X 			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
X 		}
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c
--- v2.3.3/linux/net/irda/irlan/irlan_client_event.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlan/irlan_client_event.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 12:23:22 1999
+ * Modified at:   Thu May  6 13:42:38 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 
@@ -97,7 +97,7 @@
X 	ASSERT(self != NULL, return -1;);
X 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
X 	
-	switch(event) {
+	switch (event) {
X 	case IRLAN_DISCOVERY_INDICATION:
X 		/* Get some values from peer IAS */
X 		iriap_getvaluebyclass_request(
@@ -152,7 +152,7 @@
X 		irlan_next_client_state(self, IRLAN_IDLE);
X 
X 		/* Give the client a kick! */
-		if ((self->access_type == ACCESS_PEER) && 
+		if ((self->provider.access_type == ACCESS_PEER) && 
X 		    (self->provider.state != IRLAN_IDLE))
X 			irlan_client_wakeup(self, self->saddr, self->daddr);
X 		break;
@@ -222,7 +222,7 @@
X 
X 	ASSERT(self != NULL, return -1;);
X 	
-	switch(event) {
+	switch (event) {
X 	case IRLAN_DATA_INDICATION:
X 		ASSERT(skb != NULL, return -1;);
X 	
@@ -314,7 +314,7 @@
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 48'
echo 'File patch-2.3.4 is continued in part 49'
echo 49 > _shar_seq_.tmp
#!/bin/sh
# this is part 49 of a 50 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.4 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 49; 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.3.4'
else
echo 'x - continuing with patch-2.3.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.4' &&
X 	  	ASSERT(self->dtsap_sel_data != 0, return -1;);
X 
X 		/* Check which access type we are dealing with */
-		switch(self->access_type) {
+		switch (self->client.access_type) {
X 		case ACCESS_PEER:
X 		    if (self->provider.state == IRLAN_OPEN) {
X 			    
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.3/linux/net/irda/irlan/irlan_common.c	Thu May  6 16:40:53 1999
+++ linux/net/irda/irlan/irlan_common.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,11 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 23:13:47 1999
+ * Modified at:   Sun May  9 11:48:49 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 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 
@@ -93,19 +94,25 @@
X static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
X 				__u8 value_byte, __u16 value_short, 
X 				__u8 *value_array, __u16 value_len);
-static void irlan_close_tsaps(struct irlan_cb *self);
+void irlan_close_tsaps(struct irlan_cb *self);
X 
X #ifdef CONFIG_PROC_FS
X static int irlan_proc_read(char *buf, char **start, off_t offset, int len, 
X 			   int unused);
X 
X extern struct proc_dir_entry *proc_irda;
-#endif
+#endif /* CONFIG_PROC_FS */
X 
+/*
+ * Function irlan_watchdog_timer_expired (data)
+ *
+ *    
+ *
+ */
X void irlan_watchdog_timer_expired(unsigned long data)
X {
X 	struct irmanager_event mgr_event;
-	struct irlan_cb *self, *entry;
+	struct irlan_cb *self;
X 	
X 	DEBUG(0, __FUNCTION__ "()\n");
X 
@@ -116,6 +123,7 @@
X 
X 	/* Check if device still configured */
X 	if (self->dev.start) {
+		DEBUG(0, __FUNCTION__ "(), notifying irmanager to stop irlan!\n");
X 		mgr_event.event = EVENT_IRLAN_STOP;
X 		sprintf(mgr_event.devname, "%s", self->ifname);
X 		irmanager_notify(&mgr_event);
@@ -128,22 +136,13 @@
X 		 */
X 		self->notify_irmanager = FALSE;
X 	} else {
-		DEBUG(0, __FUNCTION__ "(), recycling instance!\n");
+		DEBUG(0, __FUNCTION__ "(), closing instance!\n");
X 		if (self->netdev_registered) {
X 			DEBUG(0, __FUNCTION__ "(), removing netdev!\n");
X 			unregister_netdev(&self->dev);
X 			self->netdev_registered = FALSE;
X 		}
-
-		/* Unbind from daddr */
-		entry = hashbin_remove(irlan, self->daddr, NULL);
-		ASSERT(entry == self, return;);
-
-		self->daddr = DEV_ADDR_ANY;
-		self->saddr = DEV_ADDR_ANY;
-
-		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
-		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+		irlan_close(self);
X 	}
X }
X 
@@ -195,12 +194,12 @@
X 	/* Register with IrLMP as a service */
X  	skey = irlmp_register_service(hints);
X 
-	/* Start the first IrLAN instance */
+	/* Start the master IrLAN instance */
X  	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
X 
-	irlan_open_data_tsap(new);
- 	irlan_client_open_ctrl_tsap(new);
+	/* The master will only open its (listen) control TSAP */
X 	irlan_provider_open_ctrl_tsap(new);
+	new->master = TRUE;
X 
X 	/* Do some fast discovery! */
X 	irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
@@ -293,7 +292,7 @@
X 	self->daddr = daddr;
X 
X 	/* Provider access can only be PEER, DIRECT, or HOSTED */
-	self->access_type = access;
+	self->provider.access_type = access;
X 	self->media = MEDIA_802_3;
X 
X 	self->notify_irmanager = TRUE;
@@ -359,8 +358,11 @@
X 
X 	/* Check if device is still configured */
X 	if (self->dev.start) {
-		DEBUG(2, __FUNCTION__ 
+		DEBUG(0, __FUNCTION__ 
X 		       "(), Device still configured, closing later!\n");
+
+		/* Give it a chance to reconnect */
+		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
X 		return;
X 	}
X 	DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
@@ -371,8 +373,15 @@
X         __irlan_close(self);
X }
X 
+/*
+ * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
+ *
+ *    Here we receive the connect indication for the data channel
+ *
+ */
X void irlan_connect_indication(void *instance, void *sap, 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 irlan_cb *self;
X 	struct tsap_cb *tsap;
@@ -386,13 +395,17 @@
X 	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 	ASSERT(tsap == self->tsap_data,return;);
X 
-	DEBUG(2, "IrLAN, We are now connected!\n");
+	self->max_sdu_size = max_sdu_size;
+	self->max_header_size = max_header_size;
+
+	DEBUG(0, "IrLAN, We are now connected!\n");
+
X 	del_timer(&self->watchdog_timer);
X 
X 	irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
X 	irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
X 
-	if (self->access_type == ACCESS_PEER) {
+	if (self->provider.access_type == ACCESS_PEER) {
X 		/* 
X 		 * Data channel is open, so we are now allowed to
X 		 * configure the remote filter 
@@ -400,12 +413,13 @@
X 		irlan_get_unicast_addr(self);
X 		irlan_open_unicast_addr(self);
X 	}
-	/* Ready to transfer Ethernet frames */
+	/* Ready to transfer Ethernet frames (at last) */
X 	self->dev.tbusy = 0;
X }
X 
X void irlan_connect_confirm(void *instance, void *sap, 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 irlan_cb *self;
X 
@@ -416,6 +430,9 @@
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 
+ self->max_sdu_size = max_sdu_size;
+	self->max_header_size = max_header_size;
+
X 	/* TODO: we could set the MTU depending on the max_sdu_size */
X 
X 	DEBUG(2, "IrLAN, We are now connected!\n");
@@ -444,7 +461,7 @@
X 	struct irlan_cb *self;
X 	struct tsap_cb *tsap;
X 
-	DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason);
+	DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason);
X 	
X 	self = (struct irlan_cb *) instance;
X 	tsap = (struct tsap_cb *) sap;
@@ -460,7 +477,7 @@
X 
X 	switch(reason) {
X 	case LM_USER_REQUEST: /* User request */
-		//irlan_close(self);
+		irlan_close(self);
X 		break;
X 	case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
X 		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
@@ -490,7 +507,7 @@
X 	struct notify_t notify;
X 	struct tsap_cb *tsap;
X 
-	DEBUG(4, __FUNCTION__ "()\n");
+ DEBUG(0, __FUNCTION__ "()\n");
X 
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -500,7 +517,7 @@
X 		return;
X 
X 	irda_notify_init(¬ify);
-
+	
X 	notify.data_indication       = irlan_eth_receive;
X 	notify.udata_indication      = irlan_eth_receive;
X 	notify.connect_indication    = irlan_connect_indication;
@@ -620,7 +637,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -651,7 +668,7 @@
X 	if (!skb)
X 		return;
X 
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -683,7 +700,7 @@
X 	if (!skb)
X 		return;
X 
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -719,7 +736,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -757,7 +774,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -796,7 +813,7 @@
X 		return;
X 	
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -836,7 +853,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -871,7 +888,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_reserve(skb, self->client.max_header_size);
X 	skb_put(skb, 2);
X 	
X 	frame = skb->data;
@@ -1033,7 +1050,7 @@
X 	
X 	/* get parameter name */
X 	memcpy(name, buf+n, name_len);
-	name[ name_len] = '\0';
+	name[name_len] = '\0';
X 	n+=name_len;
X 	
X 	/*  
@@ -1051,7 +1068,7 @@
X 
X 	/* get parameter value */
X 	memcpy(value, buf+n, val_len);
-	value[ val_len] = '\0';
+	value[val_len] = '\0';
X 	n+=val_len;
X 	
X 	DEBUG(4, "Parameter: %s ", name); 
@@ -1085,31 +1102,35 @@
X 	while (self != NULL) {
X 		ASSERT(self->magic == IRLAN_MAGIC, return len;);
X 		
-		len += sprintf(buf+len, "ifname: %s,\n",
-			       self->ifname);
-		len += sprintf(buf+len, "client state: %s, ",
-			       irlan_state[ self->client.state]);
-		len += sprintf(buf+len, "provider state: %s,\n",
-			       irlan_state[ self->provider.state]);
-		len += sprintf(buf+len, "saddr: %#08x, ",
-			       self->saddr);
-		len += sprintf(buf+len, "daddr: %#08x\n",
-			       self->daddr);
-		len += sprintf(buf+len, "version: %d.%d,\n",
-			       self->version[1], self->version[0]);
-		len += sprintf(buf+len, "access type: %s\n", 
-			       irlan_access[ self->access_type]);
-		len += sprintf(buf+len, "media: %s\n", 
-			       irlan_media[ self->media]);
-
-		len += sprintf(buf+len, "local filter:\n");
-		len += sprintf(buf+len, "remote filter: ");
-		len += irlan_print_filter(self->client.filter_type, buf+len);
-
-		len += sprintf(buf+len, "tx busy: %s\n", self->dev.tbusy ? 
-			       "TRUE" : "FALSE");
-
-		len += sprintf(buf+len, "\n");
+		/* Don't display the master server */
+		if (self->master == 0) {
+			len += sprintf(buf+len, "ifname: %s,\n",
+				       self->ifname);
+			len += sprintf(buf+len, "client state: %s, ",
+				       irlan_state[ self->client.state]);
+			len += sprintf(buf+len, "provider state: %s,\n",
+				       irlan_state[ self->provider.state]);
+			len += sprintf(buf+len, "saddr: %#08x, ",
+				       self->saddr);
+			len += sprintf(buf+len, "daddr: %#08x\n",
+				       self->daddr);
+			len += sprintf(buf+len, "version: %d.%d,\n",
+				       self->version[1], self->version[0]);
+			len += sprintf(buf+len, "access type: %s\n", 
+				       irlan_access[self->client.access_type]);
+			len += sprintf(buf+len, "media: %s\n", 
+				       irlan_media[self->media]);
+			
+			len += sprintf(buf+len, "local filter:\n");
+			len += sprintf(buf+len, "remote filter: ");
+			len += irlan_print_filter(self->client.filter_type, 
+						  buf+len);
+			
+			len += sprintf(buf+len, "tx busy: %s\n", 
+				       self->dev.tbusy ? "TRUE" : "FALSE");
+			
+			len += sprintf(buf+len, "\n");
+		}
X 
X 		self = (struct irlan_cb *) hashbin_get_next(irlan);
X  	} 
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.3.3/linux/net/irda/irlan/irlan_eth.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlan/irlan_eth.c	Sun May 30 10:27:04 1999
@@ -6,13 +6,13 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Thu Apr 22 14:26:39 1999
+ * Modified at:   Mon May 10 20:23:49 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       skeleton.c by Donald Becker <bec...@CESDIS.gsfc.nasa.gov>
X  *                slip.c by Laurence Culhane,   <l...@holmes.demon.co.uk>
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 
@@ -29,6 +29,7 @@
X #include <linux/etherdevice.h>
X #include <linux/inetdevice.h>
X #include <linux/if_arp.h>
+#include <linux/random.h>
X #include <net/arp.h>
X 
X #include <net/irda/irda.h>
@@ -67,19 +68,19 @@
X 	
X 	dev->tx_queue_len = TTP_MAX_QUEUE;
X 
-#if 0
-	/*  
-	 *  OK, since we are emulating an IrLAN sever we will have to give
-	 *  ourself an ethernet address!
-	 *  FIXME: this must be more dynamically
-	 */
-	dev->dev_addr[0] = 0x40;
-	dev->dev_addr[1] = 0x00;
-	dev->dev_addr[2] = 0x00;
-	dev->dev_addr[3] = 0x00;
-	dev->dev_addr[4] = 0x23;
-	dev->dev_addr[5] = 0x45;
-#endif
+	if (self->provider.access_type == ACCESS_DIRECT) {
+		/*  
+		 * Since we are emulating an IrLAN sever we will have to
+		 * give ourself an ethernet address!  
+		 */
+		dev->dev_addr[0] = 0x40;
+		dev->dev_addr[1] = 0x00;
+		dev->dev_addr[2] = 0x00;
+		dev->dev_addr[3] = 0x00;
+		get_random_bytes(dev->dev_addr+4, 1);
+		get_random_bytes(dev->dev_addr+5, 1);
+	}
+
X 	/* 
X 	 * Network device has now been registered, so tell irmanager about
X 	 * it, so it can be configured with network parameters
@@ -180,8 +181,6 @@
X {
X 	struct irlan_cb *self;
X 
-	DEBUG(4, __FUNCTION__ "()\n");
-	
X 	self = (struct irlan_cb *) dev->priv;
X 
X 	ASSERT(self != NULL, return 0;);
@@ -202,19 +201,19 @@
X  		dev->trans_start = jiffies;
X 	}
X 	
-	DEBUG(4, "Room left at head: %d\n", skb_headroom(skb));
-	DEBUG(4, "Room left at tail: %d\n", skb_tailroom(skb));
-	DEBUG(4, "Required room: %d\n", IRLAN_MAX_HEADER);
-	
-	/* skb headroom large enough to contain IR-headers? */
-	if ((skb_headroom(skb) < IRLAN_MAX_HEADER) || (skb_shared(skb))) {
+	/* skb headroom large enough to contain all IrDA-headers? */
+	if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
X 		struct sk_buff *new_skb = 
-			skb_realloc_headroom(skb, IRLAN_MAX_HEADER);
-		ASSERT(new_skb != NULL, return 0;);
-		ASSERT(skb_headroom(new_skb) >= IRLAN_MAX_HEADER, return 0;);
+			skb_realloc_headroom(skb, self->max_header_size);
X 
-		/*  Free original skb, and use the new one */
+		/*  We have to free the original skb anyway */
X 		dev_kfree_skb(skb);
+
+		/* Did the realloc succeed? */
+		if (new_skb == NULL)
+			return 0;
+
+		/* Use the new skb instead */
X 		skb = new_skb;
X 	} 
X 
@@ -222,31 +221,26 @@
X 	self->stats.tx_packets++;
X 	self->stats.tx_bytes += skb->len; 
X 
-	/*
-	 *  Now queue the packet in the transport layer
-	 *  FIXME: clean up the code below! DB
-	 */
-	if (self->use_udata) {
+	/* Now queue the packet in the transport layer */
+	if (self->use_udata)
X 		irttp_udata_request(self->tsap_data, skb);
-		dev->tbusy = 0;
-	
-		return 0;
-	}
-
-	if (irttp_data_request(self->tsap_data, skb) == -1) {
-		/*  
-		 *  IrTTPs tx queue is full, so we just have to drop the
-		 *  frame! You might think that we should just return -1
-		 *  and don't deallocate the frame, but that is dangerous
-		 *  since it's possible that we have replaced the original
-		 *  skb with a new one with larger headroom, and that would
-		 *  really confuse do_dev_queue_xmit() in dev.c! I have
-		 *  tried :-) DB
-		 */
-		dev_kfree_skb(skb);
-		++self->stats.tx_dropped;
+	else {
+		if (irttp_data_request(self->tsap_data, skb) < 0) {
+			/*   
+			 * IrTTPs tx queue is full, so we just have to
+			 * drop the frame! You might think that we should
+			 * just return -1 and don't deallocate the frame,
+			 * but that is dangerous since it's possible that
+			 * we have replaced the original skb with a new
+			 * one with larger headroom, and that would really
+			 * confuse do_dev_queue_xmit() in dev.c! I have
+			 * tried :-) DB 
+			 */
+			dev_kfree_skb(skb);
+			++self->stats.tx_dropped;
X 		
-		return 0;
+			return 0;
+		}
X 	}
X 	dev->tbusy = 0; /* Finished! */
X 	
@@ -314,26 +308,16 @@
X 	
X 	switch (flow) {
X 	case FLOW_STOP:
-		DEBUG(4, "IrLAN, stopping Ethernet layer\n");
-
X 		dev->tbusy = 1;
X 		break;
X 	case FLOW_START:
-		/* 
-		 *  Tell upper layers that its time to transmit frames again
-		 */
-		DEBUG(4, "IrLAN, starting Ethernet layer\n");
-
+	default:
+		/* Tell upper layers that its time to transmit frames again */
X 		dev->tbusy = 0;
X 
-		/* 
-		 *  Ready to receive more frames, so schedule the network
-		 *  layer
-		 */
+		/* Schedule network layer */
X 		mark_bh(NET_BH);		
X 		break;
-	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n");
X 	}
X }
X 
@@ -373,7 +357,7 @@
X 	in_dev = dev->ip_ptr;
X 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
X 		 in_dev->ifa_list->ifa_address,
-		 &dev, 
+		 dev, 
X 		 in_dev->ifa_list->ifa_address,
X 		 NULL, dev->dev_addr, NULL);
X }
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_event.c linux/net/irda/irlan/irlan_event.c
--- v2.3.3/linux/net/irda/irlan/irlan_event.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/irlan/irlan_event.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Oct 20 09:10:16 1998
- * Modified at:   Wed Feb  3 21:42:27 1999
+ * Modified at:   Sun May  9 21:17:44 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 
@@ -38,22 +38,22 @@
X 	"IRLAN_SYNC",
X };
X 
-void irlan_next_client_state( struct irlan_cb *self, IRLAN_STATE state) 
+void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state) 
X {
X 	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 
X 	self->client.state = state;
X }
X 
-void irlan_next_provider_state( struct irlan_cb *self, IRLAN_STATE state) 
+void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state) 
X {
X 	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
X 
-	ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 
X 	self->provider.state = state;
X }
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_filter.c linux/net/irda/irlan/irlan_filter.c
--- v2.3.3/linux/net/irda/irlan/irlan_filter.c	Thu Apr 15 05:42:42 1999
+++ linux/net/irda/irlan/irlan_filter.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Fri Jan 29 11:16:38 1999
- * Modified at:   Thu Feb 25 15:10:54 1999
+ * Modified at:   Sat May  8 15:25:23 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 
@@ -41,29 +41,29 @@
X 	    (self->provider.filter_operation == DYNAMIC))
X 	{
X 		DEBUG(0, "Giving peer a dynamic Ethernet address\n");
-
X 		self->provider.mac_address[0] = 0x40;
X 		self->provider.mac_address[1] = 0x00;
X 		self->provider.mac_address[2] = 0x00;
X 		self->provider.mac_address[3] = 0x00;
X 		
X 		/* Use arbitration value to generate MAC address */
-		if (self->access_type == ACCESS_PEER) {
+		if (self->provider.access_type == ACCESS_PEER) {
X 			self->provider.mac_address[4] = 
X 				self->provider.send_arb_val & 0xff;
X 			self->provider.mac_address[5] = 
X 				(self->provider.send_arb_val >> 8) & 0xff;;
X 		} else {
X 			/* Just generate something for now */
-			self->provider.mac_address[4] = jiffies & 0xff;
-			self->provider.mac_address[5] = (jiffies >> 8) & 0xff;
+			get_random_bytes(self->provider.mac_address+4, 1);
+			get_random_bytes(self->provider.mac_address+5, 1);
X 		}
X 
X 		skb->data[0] = 0x00; /* Success */
X 		skb->data[1] = 0x03;
X 		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
X 		irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
-		irlan_insert_array_param(skb, "FILTER_ENTRY", self->provider.mac_address, 6);
+		irlan_insert_array_param(skb, "FILTER_ENTRY", 
+					 self->provider.mac_address, 6);
X 		return;
X 	}
X 	
@@ -138,8 +138,7 @@
X  *    Check parameters in request from peer device
X  *
X  */
-void irlan_check_command_param(struct irlan_cb *self, char *param, 
-			       char *value)
+void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
X {
X 	__u8 *bytes;
X 
@@ -210,6 +209,12 @@
X 	}
X }
X 
+/*
+ * Function irlan_print_filter (filter_type, buf)
+ *
+ *    Print status of filter. Used by /proc file system
+ *
+ */
X int irlan_print_filter(int filter_type, char *buf)
X {
X 	int len = 0;
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c
--- v2.3.3/linux/net/irda/irlan/irlan_provider.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlan/irlan_provider.c	Sun May 30 10:27:04 1999
@@ -6,13 +6,14 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 14:28:52 1999
+ * Modified at:   Sun May  9 12:22:56 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       skeleton.c by Donald Becker <bec...@CESDIS.gsfc.nasa.gov>
X  *                slip.c by Laurence Culhane,   <l...@holmes.demon.co.uk>
X  *                          Fred N. van Kempen, <wal...@uwalt.nl.mugnet.org>
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 
@@ -31,6 +32,7 @@
X #include <linux/netdevice.h>
X #include <linux/etherdevice.h>
X #include <linux/init.h>
+#include <linux/random.h>
X 
X #include <asm/system.h>
X #include <asm/bitops.h>
@@ -50,14 +52,20 @@
X #include <net/irda/irlan_filter.h>
X #include <net/irda/irlan_client.h>
X 
+static void irlan_provider_connect_indication(void *instance, void *sap, 
+					      struct qos_info *qos, 
+					      __u32 max_sdu_size,
+					      __u8 max_header_size,
+					      struct sk_buff *skb);
+
X /*
X  * Function irlan_provider_control_data_indication (handle, skb)
X  *
X  *    This function gets the data that is received on the control channel
X  *
X  */
-int irlan_provider_data_indication(void *instance, void *sap, 
-				   struct sk_buff *skb) 
+static int irlan_provider_data_indication(void *instance, void *sap, 
+					  struct sk_buff *skb) 
X {
X 	struct irlan_cb *self;
X 	__u8 code;
@@ -111,14 +119,17 @@
X  *    Got connection from peer IrLAN layer
X  *
X  */
-void irlan_provider_connect_indication(void *instance, void *sap, 
-				       struct qos_info *qos,
-				       __u32 max_sdu_size, struct sk_buff *skb)
+static void irlan_provider_connect_indication(void *instance, void *sap, 
+					      struct qos_info *qos,
+					      __u32 max_sdu_size, 
+					      __u8 max_header_size,
+					       struct sk_buff *skb)
X {
-	struct irlan_cb *self, *entry, *new;
+	struct irlan_cb *self, *new;
X 	struct tsap_cb *tsap;
+	__u32 saddr, daddr;
X 
-	DEBUG(2, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
X 	
X 	self = (struct irlan_cb *) instance;
X 	tsap = (struct tsap_cb *) sap;
@@ -126,34 +137,69 @@
X 	ASSERT(self != NULL, return;);
X 	ASSERT(self->magic == IRLAN_MAGIC, return;);
X 	
+	self->provider.max_sdu_size = max_sdu_size;
+	self->provider.max_header_size = max_header_size;
+
X 	ASSERT(tsap == self->provider.tsap_ctrl,return;);
X 	ASSERT(self->provider.state == IRLAN_IDLE, return;);
X 
-	/* Check if this provider is currently unused */
-	if (self->daddr == DEV_ADDR_ANY) {
-		/*
-		 * Rehash instance, now we have a client (daddr) to serve.
-		 */
-		entry = hashbin_remove(irlan, self->daddr, NULL);
-		ASSERT( entry == self, return;);
-		
-		self->daddr = irttp_get_daddr(tsap);
-		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
-		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+	daddr = irttp_get_daddr(tsap);
+	saddr = irttp_get_saddr(tsap);
+
+	/* Check if we already dealing with this client or peer */
+	new = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
+      	if (new) {
+		ASSERT(new->magic == IRLAN_MAGIC, return;);
+		DEBUG(0, __FUNCTION__ "(), found instance!\n");
+
+		/* Update saddr, since client may have moved to a new link */
+		new->saddr = saddr;
+		DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr);
+
+		/* Make sure that any old provider control TSAP is removed */
+		if ((new != self) && new->provider.tsap_ctrl) {
+			irttp_disconnect_request(new->provider.tsap_ctrl, 
+						 NULL, P_NORMAL);
+			irttp_close_tsap(new->provider.tsap_ctrl);
+			new->provider.tsap_ctrl = NULL;
+		}
X 	} else {
-		/*
-		 * If we already have the daddr set, this means that the
-		 * client must already have started (peer mode). We must
-		 * make sure that this connection attempt is from the same
-		 * device as the client is dealing with!  
+		/* This must be the master instance, so start a new instance */
+		DEBUG(0, __FUNCTION__ "(), starting new provider!\n");
+
+		new = irlan_open(saddr, daddr, TRUE); 
+	}
+
+	/*  
+	 * Check if the connection came in on the master server, or the
+	 * slave server. If it came on the slave, then everything is
+	 * really, OK (reconnect), if not we need to dup the connection and
+	 * hand it over to the slave.  
+	 */
+	if (new != self) {
+				
+		/* Now attach up the new "socket" */
+		new->provider.tsap_ctrl = irttp_dup(self->provider.tsap_ctrl, 
+						    new);
+		if (!new->provider.tsap_ctrl) {
+			DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+			return;
+		}
+		
+		/* new->stsap_sel = new->tsap->stsap_sel; */
+		new->dtsap_sel_ctrl = new->provider.tsap_ctrl->dtsap_sel;
+
+		/* Clean up the original one to keep it in listen state */
+		self->provider.tsap_ctrl->dtsap_sel = LSAP_ANY;
+		self->provider.tsap_ctrl->lsap->dlsap_sel = LSAP_ANY;
+		self->provider.tsap_ctrl->lsap->lsap_state = LSAP_DISCONNECTED;
+		
+		/* 
+		 * Use the new instance from here instead of the master
+		 * struct! 
X 		 */
-		ASSERT(self->daddr == irttp_get_daddr(tsap), return;);
+		self = new;
X 	}
-	
-	/* Update saddr, since client may have moved to a new link */
-	self->saddr = irttp_get_saddr(tsap);
-	DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", self->saddr);
-	
X 	/* Check if network device has been registered */
X 	if (!self->netdev_registered)
X 		irlan_register_netdev(self);
@@ -165,9 +211,10 @@
X 	 * indication it needs to make progress. If the client is still in 
X 	 * IDLE state, we must kick it to 
X 	 */
-	if ((self->access_type == ACCESS_PEER) && 
- (self->client.state == IRLAN_IDLE))
+	if ((self->provider.access_type == ACCESS_PEER) && 
+ (self->client.state == IRLAN_IDLE)) {
X 		irlan_client_wakeup(self, self->saddr, self->daddr);
+	}
X }
X 
X /*
@@ -225,6 +272,9 @@
X 	
X 	ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb);
X 
+	/* Open data channel */
+	irlan_open_data_tsap(self);
+
X 	return ret;
X }
X 
@@ -314,7 +364,7 @@
X 		return;
X 
X 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->provider.max_header_size);
X 	skb_put(skb, 2);
X        
X 	switch (command) {
@@ -334,6 +384,7 @@
X 		}
X 		irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
X 		break;
+
X 	case CMD_GET_MEDIA_CHAR:
X 		skb->data[0] = 0x00; /* Success */
X 		skb->data[1] = 0x05; /* 5 parameters */
@@ -341,7 +392,7 @@
X 		irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
X 		irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
X 
-		switch(self->access_type) {
+		switch (self->provider.access_type) {
X 		case ACCESS_DIRECT:
X 			irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
X 			break;
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_provider_event.c linux/net/irda/irlan/irlan_provider_event.c
--- v2.3.3/linux/net/irda/irlan/irlan_provider_event.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlan/irlan_provider_event.c	Sun May 30 10:27:04 1999
@@ -6,10 +6,10 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 10:46:28 1999
+ * Modified at:   Fri May  7 10:53:58 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 
@@ -108,7 +108,7 @@
X 	switch(event) {
X 	case IRLAN_GET_INFO_CMD:
X 		/* Be sure to use 802.3 in case of peer mode */
-		if (self->access_type == ACCESS_PEER) {
+		if (self->provider.access_type == ACCESS_PEER) {
X 			self->media = MEDIA_802_3;
X 			
X 			/* Check if client has started yet */
@@ -129,7 +129,7 @@
X 		break;		
X 	case IRLAN_OPEN_DATA_CMD:
X 		ret = irlan_parse_open_data_cmd(self, skb);
-		if (self->access_type == ACCESS_PEER) {
+		if (self->provider.access_type == ACCESS_PEER) {
X 			/* FIXME: make use of random functions! */
X 			self->provider.send_arb_val = (jiffies & 0xffff);
X 		}
@@ -205,8 +205,6 @@
X static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
X 				     struct sk_buff *skb) 
X {
-	struct irmanager_event mgr_event;
-
X 	DEBUG(4, __FUNCTION__ "()\n");
X 
X 	ASSERT(self != NULL, return -1;);
@@ -220,10 +218,6 @@
X 		break;
X 	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
X 	case IRLAN_LAP_DISCONNECT:
-		mgr_event.event = EVENT_IRLAN_STOP;
-		sprintf(mgr_event.devname, "%s", self->ifname);
-		irmanager_notify(&mgr_event);
-
X 		irlan_next_provider_state(self, IRLAN_IDLE);
X 		break;
X 	default:
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlap_comp.c linux/net/irda/irlap_comp.c
--- v2.3.3/linux/net/irda/irlap_comp.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/irlap_comp.c	Sun May 30 10:27: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.3.3/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.3.3/linux/net/irda/irlap_event.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlap_event.c	Sun May 30 10:27:04 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:   Sun May  9 22:44:32 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  *     
@@ -274,22 +274,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 +310,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 +393,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 +529,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 +567,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 +669,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 +704,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); 
@@ -1570,7 +1573,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,27 +1603,32 @@
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 		}
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.3/linux/net/irda/irlap_frame.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlap_frame.c	Sun May 30 10:27:04 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:   Sun May  9 22:55:11 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 
@@ -1056,8 +1056,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 
@@ -1254,7 +1254,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 +1279,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.3.3/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.3.3/linux/net/irda/irlmp.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlmp.c	Sun May 30 10:27:04 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:   Sun May  9 22:45:06 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,36 @@
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(0, __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);
+	lap_header_size = irlap_get_header_size(self->lap->irlap);
+
+	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER-
+		lap_header_size;
+	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
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 */
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 +481,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 +507,35 @@
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);
+	lap_header_size = irlap_get_header_size(self->lap->irlap);
+
+	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER-
+		lap_header_size;
+	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
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 +639,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 +656,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 +998,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 +1441,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 +1472,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]);
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.3.3/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.3.3/linux/net/irda/irlmp_frame.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlmp_frame.c	Sun May 30 10:27:04 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:   Sun May  9 21:00:05 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.
@@ -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.3.3/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c
--- v2.3.3/linux/net/irda/irlpt/irlpt_cli.c	Thu May  6 16:40:53 1999
+++ linux/net/irda/irlpt/irlpt_cli.c	Sun May 30 10:27: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.3.3/linux/net/irda/irlpt/irlpt_cli_fsm.c linux/net/irda/irlpt/irlpt_cli_fsm.c
--- v2.3.3/linux/net/irda/irlpt/irlpt_cli_fsm.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/irlpt/irlpt_cli_fsm.c	Sun May 30 10:27: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.3.3/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
--- v2.3.3/linux/net/irda/irlpt/irlpt_common.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/irlpt/irlpt_common.c	Sun May 30 10:27: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__
SHAR_EOF
true || echo 'restore of patch-2.3.4 failed'
fi
echo 'End of  part 49'
echo 'File patch-2.3.4 is continued in part 50'
echo 50 > _shar_seq_.tmp