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

Linux Kernel Patch v2.3, patch-2.3.6 (00/27)

26 views
Skip to first unread message

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part00

lines added deleted
linux/CREDITS : 7 -1 -1
linux/Documentation/Configure.help : 54 24 2
linux/Documentation/filesystems/hpfs.txt : 121 62 27
linux/Documentation/mtrr.txt : 14 3 1
linux/MAINTAINERS : 33 18 8
linux/Makefile : 25 12 0
linux/arch/alpha/kernel/ptrace.c : 7 1 1
linux/arch/alpha/lib/memcpy.c : 26 0 20
linux/arch/arm/kernel/ptrace.c : 154 77 11
linux/arch/i386/Makefile : 25 0 19
linux/arch/i386/boot/bootsect.S : 13 7 0
linux/arch/i386/config.in : 14 2 2
linux/arch/i386/defconfig : 19 6 0
linux/arch/i386/kernel/mca.c : 45 18 0
linux/arch/i386/kernel/ptrace.c : 106 29 18
linux/arch/i386/kernel/setup.c : 25 0 19
linux/arch/i386/kernel/signal.c : 43 15 7
linux/arch/i386/mm/init.c : 7 1 0
linux/arch/i386/mm/ioremap.c : 19 4 1
linux/arch/i386/vmlinux.lds : 34 8 9
linux/arch/i386/vmlinux.lds.S : 14 2 2
linux/arch/m68k/kernel/ptrace.c : 69 69 0
linux/arch/mips/kernel/irixelf.c : 25 0 19
linux/arch/mips/kernel/ptrace.c : 42 4 11
linux/arch/mips/kernel/sysirix.c : 25 0 19
linux/arch/ppc/chrpboot/Makefile : 29 3 6
linux/arch/ppc/chrpboot/main.c : 31 5 5
linux/arch/ppc/chrpboot/mknote.c : 72 12 18
linux/arch/ppc/coffboot/zlib.c : 43 43 0
linux/arch/ppc/common_defconfig : 20 6 1
linux/arch/ppc/config.in : 157 62 14
linux/arch/ppc/defconfig : 7 1 0
linux/arch/ppc/kernel/chrp_pci.c : 121 34 13
linux/arch/ppc/kernel/chrp_setup.c : 106 74 5
linux/arch/ppc/kernel/head.S : 145 61 26
linux/arch/ppc/kernel/idle.c : 24 1 3
linux/arch/ppc/kernel/irq.c : 14 2 1
linux/arch/ppc/kernel/misc.S : 14 1 2
linux/arch/ppc/kernel/prom.c : 11 4 0
linux/arch/ppc/kernel/ptrace.c : 94 23 7
linux/arch/ppc/kernel/smp.c : 25 0 19
linux/arch/ppc/kernel/syscalls.c : 19 4 1
linux/arch/ppc/kernel/time.c : 23 5 9
linux/arch/ppc/mm/init.c : 25 6 2
linux/arch/ppc/xmon/xmon.c : 15 2 2
linux/arch/sparc/Makefile : 8 1 1
linux/arch/sparc/kernel/ebus.c : 14 2 2
linux/arch/sparc/kernel/entry.S : 161 75 17
linux/arch/sparc/kernel/head.S : 59 49 1
linux/arch/sparc/kernel/pcic.c : 45 9 3
linux/arch/sparc/kernel/ptrace.c : 581 325 94
linux/arch/sparc/kernel/setup.c : 26 0 20
linux/arch/sparc/kernel/sys_sunos.c : 13 2 1
linux/arch/sparc64/Makefile : 27 2 6
linux/arch/sparc64/defconfig : 14 2 2
linux/arch/sparc64/kernel/binfmt_aout32.c : 8 2 0
linux/arch/sparc64/kernel/ioctl32.c : 82 16 23
linux/arch/sparc64/kernel/ptrace.c : 48 23 1
linux/arch/sparc64/kernel/signal.c : 26 0 20
linux/arch/sparc64/kernel/sys_sparc.c : 110 8 60
linux/arch/sparc64/kernel/sys_sparc32.c : 45 1 34
linux/arch/sparc64/kernel/sys_sunos32.c : 119 42 31
linux/arch/sparc64/kernel/systbls.S : 27 2 6
linux/arch/sparc64/kernel/traps.c : 14 2 2
linux/arch/sparc64/math-emu/sfp-util.h : 25 9 4
linux/drivers/Makefile : 14 2 2
linux/drivers/block/cy82c693.c : 15 9 0
linux/drivers/block/floppy.c : 9 2 1
linux/drivers/block/ide-pmac.c : 17 1 3
linux/drivers/block/ll_rw_blk.c : 43 7 13
linux/drivers/block/ns87415.c : 16 3 0
linux/drivers/block/piix.c : 17 4 2
linux/drivers/block/rd.c : 252 88 52
linux/drivers/char/adbmouse.c : 8 1 1
linux/drivers/char/bttv.c : 8 1 1
linux/drivers/char/bttv.h : 59 25 0
linux/drivers/char/misc.c : 47 19 1
linux/drivers/char/radio-cadet.c : 19 5 1
linux/drivers/char/rtc.c : 35 7 8
linux/drivers/char/tuner.c : 130 53 10
linux/drivers/char/tuner.h : 10 3 1
linux/drivers/i2o/Config.in : 7 1 0
linux/drivers/i2o/Makefile : 12 12 0
linux/drivers/i2o/README : 75 75 0
linux/drivers/i2o/README.ioctl : 78 78 0
linux/drivers/i2o/README.lan : 398 398 0
linux/drivers/i2o/i2o_block.c : 38 38 0
linux/drivers/i2o/i2o_config.c : 1071 1071 0
linux/drivers/i2o/i2o_core.c : 613 613 0
linux/drivers/i2o/i2o_lan.c : 2053 2053 0
linux/drivers/i2o/i2o_lan.h : 853 853 0
linux/drivers/i2o/i2o_pci.c : 112 112 0
linux/drivers/i2o/i2o_proc.c : 243 243 0
linux/drivers/i2o/i2o_proc.h : 2382 2382 0
linux/drivers/i2o/i2o_scsi.c : 141 141 0
linux/drivers/i2o/i2o_scsi.h : 871 871 0
linux/drivers/macintosh/Makefile : 48 48 0
linux/drivers/macintosh/adb.c : 8 2 0
linux/drivers/macintosh/mac_keyb.c : 34 4 3
linux/drivers/macintosh/macserial.c : 7 0 1
linux/drivers/misc/BUGS-parport : 52 8 8
linux/drivers/misc/Makefile : 4 1 0
linux/drivers/misc/TODO-parport : 10 4 0
linux/drivers/misc/parport_amiga.c : 5 2 0
linux/drivers/misc/parport_arc.c : 60 10 20
linux/drivers/misc/parport_atari.c : 81 28 11
linux/drivers/misc/parport_ax.c : 64 11 20
linux/drivers/misc/parport_init.c : 111 26 37
linux/drivers/misc/parport_mfc3.c : 50 12 5
linux/drivers/misc/parport_pc.c : 53 10 16
linux/drivers/misc/parport_procfs.c : 456 225 80
linux/drivers/misc/parport_share.c : 726 321 296
linux/drivers/net/3c515.c : 90 9 40
linux/drivers/net/Config.in : 23 3 0
linux/drivers/net/Makefile : 20 7 0
linux/drivers/net/Space.c : 48 28 0
linux/drivers/net/cosa.c : 17 4 0
linux/drivers/net/cs89x0.c : 35 8 1
linux/drivers/net/cycx_drv.c : 8 1 1
linux/drivers/net/cycx_main.c : 663 663 0
linux/drivers/net/cycx_x25.c : 377 377 0
linux/drivers/net/irda/Config.in : 1538 1538 0
linux/drivers/net/irda/Makefile : 7 1 0
linux/drivers/net/irda/actisys.c : 76 56 0
linux/drivers/net/irda/esi.c : 39 3 8
linux/drivers/net/irda/girbil.c : 37 3 7
linux/drivers/net/irda/irport.c : 75 11 11
linux/drivers/net/irda/litelink.c : 509 168 84
linux/drivers/net/irda/pc87108.c : 110 15 18
linux/drivers/net/irda/smc-ircc.c : 423 107 106
linux/drivers/net/irda/tekram.c : 969 969 0
linux/drivers/net/irda/uircc.c : 91 14 13
linux/drivers/net/irda/w83977af_ir.c : 44 5 5
linux/drivers/net/myri_sbus.c : 26 1 5
linux/drivers/net/ni52.c : 7 1 0
linux/drivers/net/ni52.h : 8 1 1
linux/drivers/net/ni65.c : 8 1 1
linux/drivers/net/ptifddi.c : 36 6 2
linux/drivers/net/sdladrv.c : 5 1 1
linux/drivers/net/sdlamain.c : 33 1 5
linux/drivers/net/sk_mca.c : 24 3 1
linux/drivers/net/sk_mca.h : 1143 1143 0
linux/drivers/pci/oldproc.c : 175 174 0
linux/drivers/sbus/char/Config.in : 81 23 1
linux/drivers/sbus/char/aurora.c : 10 6 0
linux/drivers/sbus/char/bpp.c : 15 1 1
linux/drivers/sbus/char/pcikbd.c : 8 1 1
linux/drivers/sbus/char/rtc.c : 122 28 20
linux/drivers/sbus/char/su.c : 36 10 3
linux/drivers/sbus/char/vfc_dev.c : 611 181 195
linux/drivers/scsi/Config.in : 19 2 3
linux/drivers/scsi/README.aic7xxx : 12 2 4
linux/drivers/scsi/aic7xxx/aic7xxx.reg : 63 17 12
linux/drivers/scsi/aic7xxx/aic7xxx.seq : 145 78 0
linux/drivers/scsi/aic7xxx/scsi_message.h : 509 137 112
linux/drivers/scsi/aic7xxx.c : 13 9 1
linux/drivers/scsi/aic7xxx_proc.c : 3280 1316 669
linux/drivers/scsi/aic7xxx_reg.h : 105 32 23
linux/drivers/scsi/aic7xxx_seq.c : 91 42 0
linux/drivers/scsi/scsi.c : 986 344 315
linux/drivers/scsi/scsi.h : 18 3 2
linux/drivers/scsi/scsi_proc.c : 7 1 0
linux/drivers/scsi/scsi_syms.c : 8 1 1
linux/drivers/scsi/scsicam.c : 22 2 3
linux/drivers/scsi/sd.c : 37 4 5
linux/drivers/scsi/sg.c : 28 4 4
linux/drivers/sound/dmasound.c : 1160 407 270
linux/drivers/sound/sound_core.c : 97 52 0
linux/drivers/usb/CREDITS : 31 17 1
linux/drivers/usb/Config.in : 7 1 0
linux/drivers/usb/Makefile : 12 5 1
linux/drivers/usb/README.ohci : 31 16 0
linux/drivers/usb/acm.c : 9 6 0
linux/drivers/usb/audio.c : 34 6 6
linux/drivers/usb/cpia.c : 17 2 2
linux/drivers/usb/hub.c : 17 2 2
linux/drivers/usb/keyboard.c : 39 6 6
linux/drivers/usb/keymap-mac.c : 33 7 2
linux/drivers/usb/maps/mac.map : 50 50 0
linux/drivers/usb/mkmap.adb : 350 350 0
linux/drivers/usb/mouse.c : 88 88 0
linux/drivers/usb/ohci-debug.c : 17 2 2
linux/drivers/usb/ohci.c : 83 21 17
linux/drivers/usb/ohci.h : 729 230 141
linux/drivers/usb/printer.c : 53 14 12
linux/drivers/usb/stopusb : 35 6 5
linux/drivers/usb/uhci.c : 9 2 2
linux/drivers/usb/uhci.h : 362 150 49
linux/drivers/usb/usb-core.c : 11 2 1
linux/drivers/usb/usb-debug.c : 18 4 1
linux/drivers/usb/usb.c : 22 11 4
linux/drivers/usb/usb.h : 336 136 40
linux/drivers/usb/usb_scsi.c : 151 66 20
linux/drivers/usb/usb_scsi.h : 1098 1098 0
linux/drivers/usb/usb_scsi_debug.c : 145 145 0
linux/drivers/usb/usb_scsi_dt.c : 104 104 0
linux/drivers/video/atyfb.c : 4 4 0
linux/drivers/video/igafb.c : 192 40 21
linux/fs/Config.in : 88 32 12
linux/fs/adfs/super.c : 12 3 3
linux/fs/affs/super.c : 18 2 3
linux/fs/autofs/inode.c : 8 1 1
linux/fs/binfmt_aout.c : 8 1 1
linux/fs/binfmt_elf.c : 69 8 22
linux/fs/buffer.c : 53 6 14
linux/fs/coda/inode.c : 8 1 1
linux/fs/dcache.c : 17 2 2
linux/fs/devpts/inode.c : 8 1 1
linux/fs/efs/super.c : 8 1 1
linux/fs/ext2/super.c : 8 1 1
linux/fs/ext2/symlink.c : 8 1 1
linux/fs/fat/inode.c : 7 0 1
linux/fs/fcntl.c : 8 1 1
linux/fs/hfs/bnode.c : 74 31 22
linux/fs/hfs/btree.c : 8 2 0
linux/fs/hfs/catalog.c : 8 1 1
linux/fs/hfs/mdb.c : 8 2 0
linux/fs/hfs/super.c : 10 3 1
linux/fs/hpfs/alloc.c : 8 1 1
linux/fs/hpfs/hpfs_fn.h : 13 5 2
linux/fs/hpfs/namei.c : 8 1 1
linux/fs/hpfs/super.c : 32 6 11
linux/fs/isofs/inode.c : 8 1 1
linux/fs/minix/bitmap.c : 8 1 1
linux/fs/minix/inode.c : 35 4 4
linux/fs/minix/namei.c : 8 1 1
linux/fs/ncpfs/inode.c : 13 1 6
linux/fs/nfs/dir.c : 8 1 1
linux/fs/nfs/inode.c : 733 335 229
linux/fs/nfs/nfs2xdr.c : 101 22 10
linux/fs/nfs/proc.c : 297 104 98
linux/fs/nfs/read.c : 86 0 73
linux/fs/nfs/symlink.c : 7 1 0
linux/fs/nfs/write.c : 197 121 50
linux/fs/nfsd/export.c : 43 16 3
linux/fs/nfsd/nfsfh.c : 19 2 3
linux/fs/ntfs/fs.c : 26 3 3
linux/fs/pipe.c : 8 1 1
linux/fs/proc/Makefile : 8 1 1
linux/fs/proc/inode.c : 8 1 1
linux/fs/proc/link.c : 8 1 1
linux/fs/proc/root.c : 8 1 1
linux/fs/proc/sysvipc.c : 18 4 1
linux/fs/qnx4/inode.c : 138 138 0
linux/fs/romfs/inode.c : 8 1 1
linux/fs/smbfs/dir.c : 8 1 1
linux/fs/smbfs/inode.c : 8 1 1
linux/fs/super.c : 8 1 1
linux/fs/sysv/inode.c : 33 13 13
linux/fs/ufs/super.c : 8 1 1
linux/fs/umsdos/check.c : 8 1 1
linux/include/asm-alpha/softirq.h : 8 1 1
linux/include/asm-alpha/spinlock.h : 16 10 0
linux/include/asm-alpha/string.h : 100 29 37
linux/include/asm-alpha/system.h : 7 1 0
linux/include/asm-i386/bugs.h : 11 5 0
linux/include/asm-i386/page.h : 21 11 3
linux/include/asm-i386/page_offset.h : 11 4 1
linux/include/asm-mips/namei.h : 8 8 0
linux/include/asm-ppc/system.h : 8 1 1
linux/include/asm-sparc/io.h : 18 5 0
linux/include/asm-sparc/namei.h : 21 10 1
linux/include/asm-sparc/pcic.h : 8 1 1
linux/include/asm-sparc64/namei.h : 52 16 2
linux/include/linux/cyclomx.h : 8 1 1
linux/include/linux/cycx_cfm.h : 91 91 0
linux/include/linux/cycx_drv.h : 81 81 0
linux/include/linux/cycx_x25.h : 66 66 0
linux/include/linux/dcache.h : 103 103 0
linux/include/linux/file.h : 57 7 10
linux/include/linux/fs.h : 19 4 4
linux/include/linux/i2o.h : 277 59 65
linux/include/linux/igmp.h : 588 588 0
linux/include/linux/inet.h : 20 1 13
linux/include/linux/inetdevice.h : 7 1 0
linux/include/linux/mm.h : 8 1 1
linux/include/linux/netdevice.h : 16 3 0
linux/include/linux/nfs.h : 29 9 0
linux/include/linux/nfs_fs.h : 39 8 9
linux/include/linux/nfs_fs_i.h : 37 2 7
linux/include/linux/pagemap.h : 10 4 0
linux/include/linux/parport.h : 7 1 0
linux/include/linux/pci.h : 60 7 10
linux/include/linux/pkt_sched.h : 71 22 1
linux/include/linux/proc_fs.h : 9 3 0
linux/include/linux/rtnetlink.h : 46 11 1
linux/include/linux/sched.h : 152 15 114
linux/include/linux/sysctl.h : 79 21 24
linux/include/linux/wanrouter.h : 43 31 1
linux/include/net/addrconf.h : 49 9 2
linux/include/net/dst.h : 16 2 1
linux/include/net/if_inet6.h : 9 3 0
linux/include/net/ip.h : 15 2 0
linux/include/net/irda/dongle.h : 13 3 3
linux/include/net/irda/ircomm_common.h : 27 4 4
linux/include/net/irda/irda_device.h : 23 5 5
linux/include/net/irda/irlan_common.h : 25 3 3
linux/include/net/irda/irlan_eth.h : 36 7 2
linux/include/net/irda/irport.h : 20 3 2
linux/include/net/irda/irqueue.h : 25 4 3
linux/include/net/irda/irvtd.h : 17 1 3
linux/include/net/irda/smc-ircc.h : 18 4 1
linux/include/net/irda/smc_ircc.h : 160 160 0
linux/include/net/neighbour.h : 123 0 123
linux/include/net/pkt_cls.h : 76 16 23
linux/include/net/pkt_sched.h : 17 3 6
linux/include/net/route.h : 138 88 7
linux/include/net/tcp.h : 21 1 7
linux/include/net/udp.h : 8 1 1
linux/include/scsi/scsicam.h : 15 7 1
linux/include/scsi/sg.h : 6 2 0
linux/ipc/msg.c : 272 87 90
linux/ipc/sem.c : 95 59 1
linux/ipc/shm.c : 90 56 0
linux/kernel/ksyms.c : 96 60 0
linux/kernel/signal.c : 16 2 1
linux/kernel/sys.c : 24 3 1
linux/mm/memory.c : 8 2 0
linux/mm/mmap.c : 120 18 31
linux/mm/mremap.c : 186 110 20
linux/mm/swapfile.c : 30 2 2
linux/net/core/dev.c : 16 2 1
linux/net/core/dev_mcast.c : 497 104 131
linux/net/core/dst.c : 156 34 16
linux/net/core/neighbour.c : 66 38 4
linux/net/core/rtnetlink.c : 886 223 113
linux/net/decnet/dn_neigh.c : 90 9 21
linux/net/ethernet/eth.c : 41 10 4
linux/net/ipv4/af_inet.c : 7 1 0
linux/net/ipv4/arp.c : 17 2 2
linux/net/ipv4/devinet.c : 264 38 46
linux/net/ipv4/fib_frontend.c : 78 10 10
linux/net/ipv4/fib_hash.c : 22 1 3
linux/net/ipv4/fib_rules.c : 207 17 21
linux/net/ipv4/icmp.c : 146 21 19
linux/net/ipv4/igmp.c : 39 6 6
linux/net/ipv4/ip_input.c : 333 81 19
linux/net/ipv4/ip_masq_vdolive.c : 32 3 7
linux/net/ipv4/ip_options.c : 8 1 1
linux/net/ipv4/ipconfig.c : 8 1 1
linux/net/ipv4/ipmr.c : 24 3 3
linux/net/ipv4/route.c : 36 6 3
linux/net/ipv4/tcp_input.c : 28 4 3
linux/net/ipv4/tcp_ipv4.c : 8 1 1
linux/net/ipv4/udp.c : 8 1 1
linux/net/ipv4/utils.c : 114 51 19
linux/net/ipv6/addrconf.c : 20 6 1
linux/net/ipv6/af_inet6.c : 102 13 16
linux/net/ipv6/ip6_fw.c : 17 2 2
linux/net/ipv6/ip6_output.c : 17 2 2
linux/net/ipv6/mcast.c : 31 4 13
linux/net/ipv6/ndisc.c : 378 76 22
linux/net/ipv6/raw.c : 163 29 23
linux/net/ipv6/reassembly.c : 26 1 12
linux/net/ipv6/route.c : 8 1 1
linux/net/ipv6/tcp_ipv6.c : 46 12 3
linux/net/ipv6/udp.c : 8 1 1
linux/net/irda/Config.in : 27 1 13
linux/net/irda/af_irda.c : 54 20 23
linux/net/irda/discovery.c : 72 12 8
linux/net/irda/ircomm/ircomm_common.c : 41 8 6
linux/net/irda/ircomm/irvtd_driver.c : 168 32 27
linux/net/irda/irda_device.c : 374 114 43
linux/net/irda/irlan/irlan_client.c : 207 66 30
linux/net/irda/irlan/irlan_client_event.c : 30 8 2
linux/net/irda/irlan/irlan_common.c : 8 1 1
linux/net/irda/irlan/irlan_eth.c : 293 93 34
linux/net/irda/irlan/irlan_filter.c : 208 50 56
linux/net/irda/irlap.c : 16 2 1
linux/net/irda/irlap_event.c : 1069 273 273
linux/net/irda/irlap_frame.c : 264 31 64
linux/net/irda/irlmp.c : 44 2 15
linux/net/irda/irlmp_frame.c : 45 8 10
linux/net/irda/irmod.c : 31 6 6
linux/net/irda/irttp.c : 17 2 2
linux/net/irda/wrapper.c : 244 37 49
linux/net/netrom/nr_route.c : 52 10 6
linux/net/netsyms.c : 31 4 4
linux/net/packet/af_packet.c : 17 1 3
linux/net/rose/rose_route.c : 85 16 13
linux/net/sched/cls_api.c : 31 4 4
linux/net/sched/cls_fw.c : 118 33 8
linux/net/sched/cls_route.c : 83 14 9
linux/net/sched/cls_rsvp.h : 125 23 16
linux/net/sched/cls_u32.c : 72 12 8
linux/net/sched/estimator.c : 70 12 7
linux/net/sched/police.c : 65 19 7
linux/net/sched/sch_api.c : 96 22 3
linux/net/sched/sch_cbq.c : 234 68 19
linux/net/sched/sch_csz.c : 155 41 15
linux/net/sched/sch_generic.c : 34 4 4
linux/net/sched/sch_prio.c : 450 213 71
linux/net/sched/sch_sfq.c : 44 9 4
linux/net/sched/sch_tbf.c : 17 2 2
linux/net/sched/sch_teql.c : 17 2 2
linux/net/socket.c : 79 27 11
linux/net/sunrpc/xprt.c : 8 1 1
linux/net/wanrouter/wanmain.c : 139 64 13
linux/net/x25/af_x25.c : 56 9 6
--
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part01

#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 01 of a 27 - 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.6 ==============
if test -f 'patch-2.3.6' -a X"$1" != X"-c"; then
echo 'x - skipping patch-2.3.6 (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.3.6 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.3.6' &&
diff -u --recursive --new-file v2.3.5/linux/CREDITS linux/CREDITS
--- v2.3.5/linux/CREDITS Mon May 31 22:28:04 1999
+++ linux/CREDITS Tue Jun 8 10:27:18 1999
@@ -16,6 +16,14 @@
X S: (ask for current address)
X S: Finland
X
+N: Dragos Acostachioaie
+E: dra...@iname.com
+W: http://www.arbornet.org/~dragos
+D: /proc/sysvipc
+S: C. Negri 6, bl. D3
+S: Iasi 6600
+S: Romania
+
X N: Dave Airlie
X E: air...@linux.ie
X W: http://www.csn.ul.ie/~airlied
@@ -821,7 +829,7 @@
X S: Germany
X
X N: Michael Hipp
-E: mh...@student.uni-tuebingen.de
+E: hi...@informatik.uni-tuebingen.de
X D: drivers for the racal ni5210 & ni6510 Ethernet-boards
X S: Talstr. 1
X S: D - 72072 Tuebingen
@@ -1349,8 +1357,11 @@
X
X N: Arnaldo Carvalho de Melo
X E: ac...@conectiva.com.br
+W: http://www.conectiva.com.br/~acme
X D: wanrouter hacking
-D: cyclades 2X sync card driver (still in early devel stage)
+D: Cyclom 2X synchronous card driver
+D: i18n for minicom, net-tools, util-linux, fetchmail, etc
+S: Conectiva Informatica LTDA
X S: R. Prof. Rubens Elke Braga, 558 - Parolin
X S: 80220-320 Curitiba - Parana
X S: Brazil
@@ -1929,6 +1940,17 @@
X S: 1050 Woodduck Avenue
X S: Santa Clara, California 95051
X S: USA
+
+N: Marcelo W. Tosatti
+E: mar...@conectiva.com.br
+W: http://lie-br.conectiva.com.br/~marcelo/
+D: Miscellaneous kernel hacker
+D: Cyclom 2X driver hacker
+D: linuxconf apache & proftpd module maintainer
+S: Conectiva Informatica LTDA
+S: R. Prof. Rubens Elke Braga, 558 - Parolin
+S: 80220-320 Curitiba - Parana
+S: Brazil
X
X N: Stefan Traby
X E: ste...@quant-x.com
diff -u --recursive --new-file v2.3.5/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.5/linux/Documentation/Configure.help Mon May 31 22:28:04 1999
+++ linux/Documentation/Configure.help Wed Jun 9 16:59:15 1999
@@ -3958,34 +3958,49 @@
X say M here and read Documentation/modules.txt. The module will be
X called aic7xxx.o.
X
-Override driver defaults for commands per LUN
-CONFIG_OVERRIDE_CMDS
- Say Y here if you want to override the default maximum number of
- commands that a single device on the aic7xxx controller is allowed
- to have active at one time. This option only affects tagged queueing
- capable devices. The driver uses a value of 24 by default.
- If you say Y here, you can adjust the number of commands per LUN
- with the following configuration option.
+Enable or Disable Tagged Command Queueing by default
+CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+ This option causes the aic7xxx driver to attempt to use tagged command
+ queueing on any devices that claim to support it. If this is set to yes,
+ you can still turn off TCQ on troublesome devices with the use of the
+ tag_info boot parameter. See /usr/src/linux/drivers/scsi/README.aic7xxx
+ for more information on that and other aic7xxx setup commands. If this
+ option is turned off, you may still enable TCQ on known good devices by
+ use of the tag_info boot parameter.
X
- If unsure, say N.
-
-Maximum number of commands per LUN
-CONFIG_AIC7XXX_CMDS_PER_LUN
- Specify the maximum number of commands you would like to allocate
- per LUN (a LUN is a Logical Unit Number -- some physical SCSI
- devices, e.g. CD jukeboxes, act logically as several separate units,
- each of which gets its own number).
+ If you are unsure about your devices then it is safest to say N here.
+
+ However, TCQ can increase performance on some hard drives by as much
+ as 50% or more, so I would recommend that if you say N here, that you
+ at least read the README.aic7xxx file so you will know how to enable
+ this option manually should your drives prove to be safe in regards
+ to TCQ.
+
+ Conversely, certain drives are known to lock up or cause bus resets when
+ TCQ is enabled on them. If you have a Western Digital Enterprise SCSI
+ drive for instance, then don't even bother to enable TCQ on it as the
+ drive will become unreliable, and it will actually reduce performance.
+
+Default number of TCQ commands per device
+CONFIG_AIC7XXX_CMDS_PER_DEVICE
+ Specify the number of commands you would like to allocate per SCSI
+ device when Tagged Command Queueing (TCQ) is enabled on that device.
X
- Reasonable figures are in the range of 14 to 32 commands per device,
+ Reasonable figures are in the range of 8 to 24 commands per device,
X but depending on hardware could be increased or decreased from that
X figure. If the number is too high for any particular device, the
X driver will automatically compensate usually after only 10 minutes
- of uptime and will issue a message to alert you to the fact that the
- number of commands for that device has been reduced. It will not
- hinder performance if some of your devices eventually have their
- commands per LUN reduced, but is a waste of memory if all of your
- devices end up reducing this number down to a more reasonable
- figure. Default: 24
+ of uptime. It will not hinder performance if some of your devices
+ eventually have their command depth reduced, but is a waste of memory
+ if all of your devices end up reducing this number down to a more
+ reasonable figure.
+
+ NOTE: Certain very broken drives are known to lock up when given more
+ commands than they like to deal with. Quantum Fireball drives are the
+ most common in this category. For the Quantum Fireball drives I would
+ suggest no more than 8 commands per device.
+
+ Default: 8
X
X Collect statistics to report in /proc
X CONFIG_AIC7XXX_PROC_STATS
@@ -6369,6 +6384,20 @@
X module, say M here and read Documentation/modules.txt as well as
X Documentation/networking/net-modules.txt.
X
+SKnet MCA support
+CONFIG_SKMC
+ This are Micro Channel ethernet adapters. You need to set CONFIG_MCA
+ to use this driver. It's both available as an in-kernel driver and
+ as a module ( = code which can be inserted in and removed from the
+ running kernel whenever you want). If you want to compile it as a module,
+ say M here and read Documentation/modules.txt as well as
+ Documentation/networking/net-modules.txt. If you plan to use more than
+ one network card under linux, read the Multiple-Ethernet-mini-HOWTO,
+ available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. Supported
+ cards are the SKnet Junior MC2 and the SKnet MC2(+). Distinguishing
+ both cards is done automatically. Note that using multiple boards
+ of different type hasn't been tested with this driver.
+
X EISA, VLB, PCI and on board controllers
X CONFIG_NET_EISA
X This is another class of network cards which attach directly to the
@@ -8936,8 +8965,8 @@
X
X Zilog serial support
X CONFIG_SUN_ZS
- This driver does not exist at this point, so you might as well
- say N.
+ If you are asked this question, something is wrong with config scripts.
+ Zilog serial driver is always enabled in sparc architecture.
X
X Double Talk PC internal speech card support
X CONFIG_DTLK
@@ -10338,8 +10367,14 @@
X inserted in and removed from the running kernel whenever you want),
X say M and read Documentation/modules.txt. If unsure, say Y.
X
-#Mostek real time clock support
-#CONFIG_SUN_MOSTEK_RTC
+Mostek real time clock support
+CONFIG_SUN_MOSTEK_RTC
+ The Mostek RTC chip is used on all knows Sun computers except
+ some JavaStation-s. For a JavaStation you need to say Y both here
+ and to CONFIG_RTC.
+
+ Say Y here unless you are building a special purpose kernel.
+
X #
X #Siemens SAB82532 serial support
X #CONFIG_SAB82532
diff -u --recursive --new-file v2.3.5/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt
--- v2.3.5/linux/Documentation/filesystems/hpfs.txt Mon May 17 09:55:20 1999
+++ linux/Documentation/filesystems/hpfs.txt Fri Jun 4 01:06:29 1999
@@ -1,4 +1,4 @@
-Read/Write HPFS 1.99b
+Read/Write HPFS 2.00
X 1998-1999, Mikulas Patocka
X
X email: mik...@artax.karlin.mff.cuni.cz
@@ -267,6 +267,8 @@
X file
X Now it tries to truncate the file if there's not enough space when deleting
X Removed a lot of redundat code
+2.00 Fixed a bug in rename (it was there since 1.96)
+ Better anti-fragmentation strategy
X
X
X vim: set textwidth=80:
diff -u --recursive --new-file v2.3.5/linux/Documentation/mtrr.txt linux/Documentation/mtrr.txt
--- v2.3.5/linux/Documentation/mtrr.txt Mon May 17 09:55:20 1999
+++ linux/Documentation/mtrr.txt Thu Jun 3 08:17:28 1999
@@ -1,15 +1,25 @@
X MTRR (Memory Type Range Register) control
-16 May 1999
+3 Jun 1999
X Richard Gooch
X <rgo...@atnf.csiro.au>
X
- On Intel Pentium Pro/Pentium II systems the Memory Type Range
- Registers (MTRRs) may be used to control processor access to memory
- ranges. This is most useful when you have a video (VGA) card on a
- PCI or AGP bus. Enabling write-combining allows bus write transfers
- to be combined into a larger transfer before bursting over the
- PCI/AGP bus. This can increase performance of image write operations
- 2.5 times or more.
+ On Intel P6 family processors (Pentium Pro, Pentium II and later)
+ the Memory Type Range Registers (MTRRs) may be used to control
+ processor access to memory ranges. This is most useful when you have
+ a video (VGA) card on a PCI or AGP bus. Enabling write-combining
+ allows bus write transfers to be combined into a larger transfer
+ before bursting over the PCI/AGP bus. This can increase performance
+ of image write operations 2.5 times or more.
+
+ The Cyrix 6x86, 6x86MX and M II processors have Address Range
+ Registers (ARRs) which provide a similar functionality to MTRRs. For
+ these, the ARRs are used to emulate the MTRRs.
+
+ The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
+ MTRRs. These are supported.
+
+ The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
+ are supported.
X
X The CONFIG_MTRR option creates a /proc/mtrr file which may be used
X to manipulate your MTRRs. Typically the X server should use
diff -u --recursive --new-file v2.3.5/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.5/linux/MAINTAINERS Mon May 17 09:55:20 1999
+++ linux/MAINTAINERS Thu Jun 3 08:26:42 1999
@@ -192,6 +192,13 @@
X M: j...@acm.org
X S: Maintained
X
+CYCLADES 2X SYNC CARD DRIVER
+P: Arnaldo Carvalho de Melo
+M: ac...@conectiva.com.br
+W: http://www.conectiva.com.br/~acme
+L: cycsyn...@bazar.conectiva.com.br
+S: Maintained
+
X CYCLADES ASYNC MUX DRIVER
X P: Ivan Passos
X M: Ivan Passos <iv...@cyclades.com>
@@ -390,6 +397,11 @@
X M: Paul.R...@rustcorp.com.au
X W: http://www.rustcorp.com/linux/ipchains
X S: Supported
+
+IP MASQUERADING:
+P: Juanjo Ciarlante
+M: jjci...@raiz.uncu.edu.ar
+S: Maintained
X
X IPX/SPX NETWORK LAYER
X P: Jay Schulist
diff -u --recursive --new-file v2.3.5/linux/Makefile linux/Makefile
--- v2.3.5/linux/Makefile Wed Jun 2 14:44:39 1999
+++ linux/Makefile Wed Jun 2 14:40:19 1999
@@ -1,6 +1,6 @@
X VERSION = 2
X PATCHLEVEL = 3
-SUBLEVEL = 5
+SUBLEVEL = 6
X EXTRAVERSION =
X
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.3.5/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v2.3.5/linux/arch/alpha/kernel/ptrace.c Mon May 31 22:28:04 1999
+++ linux/arch/alpha/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -246,26 +246,6 @@
X flush_tlb();
X }
X
-static struct vm_area_struct *
-find_extend_vma(struct task_struct * tsk, unsigned long addr)
-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm,addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.
diff -u --recursive --new-file v2.3.5/linux/arch/alpha/lib/memcpy.c linux/arch/alpha/lib/memcpy.c
--- v2.3.5/linux/arch/alpha/lib/memcpy.c Tue Apr 7 08:05:05 1998
+++ linux/arch/alpha/lib/memcpy.c Mon Jun 7 11:37:13 1999
@@ -21,30 +21,44 @@
X * This should be done in one go with ldq_u*2/mask/stq_u. Do it
X * with a macro so that we can fix it up later..
X */
-#define ALIGN_DEST_TO8(d,s,n) \
+#define ALIGN_DEST_TO8_UP(d,s,n) \
X while (d & 7) { \
X if (n <= 0) return; \
X n--; \
X *(char *) d = *(char *) s; \
X d++; s++; \
X }
+#define ALIGN_DEST_TO8_DN(d,s,n) \
+ while (d & 7) { \
+ if (n <= 0) return; \
+ n--; \
+ d--; s--; \
+ *(char *) d = *(char *) s; \
+ }
X
X /*
X * This should similarly be done with ldq_u*2/mask/stq. The destination
X * is aligned, but we don't fill in a full quad-word
X */
-#define DO_REST(d,s,n) \
+#define DO_REST_UP(d,s,n) \
X while (n > 0) { \
X n--; \
X *(char *) d = *(char *) s; \
X d++; s++; \
X }
+#define DO_REST_DN(d,s,n) \
+ while (n > 0) { \
+ n--; \
+ d--; s--; \
+ *(char *) d = *(char *) s; \
+ }
X
X /*
X * This should be done with ldq/mask/stq. The source and destination are
X * aligned, but we don't fill in a full quad-word
X */
-#define DO_REST_ALIGNED(d,s,n) DO_REST(d,s,n)
+#define DO_REST_ALIGNED_UP(d,s,n) DO_REST_UP(d,s,n)
+#define DO_REST_ALIGNED_DN(d,s,n) DO_REST_DN(d,s,n)
X
X /*
X * This does unaligned memory copies. We want to avoid storing to
@@ -53,9 +67,10 @@
X *
X * Note the ordering to try to avoid load (and address generation) latencies.
X */
-static inline void __memcpy_unaligned(unsigned long d, unsigned long s, long n)
+static inline void __memcpy_unaligned_up (unsigned long d, unsigned long s,
+ long n)
X {
- ALIGN_DEST_TO8(d,s,n);
+ ALIGN_DEST_TO8_UP(d,s,n);
X n -= 8; /* to avoid compare against 8 in the loop */
X if (n >= 0) {
X unsigned long low_word, high_word;
@@ -77,7 +92,17 @@
X } while (n >= 0);
X }
X n += 8;
- DO_REST(d,s,n);
+ DO_REST_UP(d,s,n);
+}
+
+static inline void __memcpy_unaligned_dn (unsigned long d, unsigned long s,
+ long n)
+{
+ /* I don't understand AXP assembler well enough for this. -Tim */
+ s += n;
+ d += n;
+ while (n--)
+ * (char *) --d = * (char *) --s;
X }
X
X /*
@@ -88,9 +113,10 @@
X *
X * Note the ordering to try to avoid load (and address generation) latencies.
X */
-static inline void __memcpy_aligned(unsigned long d, unsigned long s, long n)
+static inline void __memcpy_aligned_up (unsigned long d, unsigned long s,
+ long n)
X {
- ALIGN_DEST_TO8(d,s,n);
+ ALIGN_DEST_TO8_UP(d,s,n);
X n -= 8;
X while (n >= 0) {
X unsigned long tmp;
@@ -101,18 +127,58 @@
X d += 8;
X }
X n += 8;
- DO_REST_ALIGNED(d,s,n);
+ DO_REST_ALIGNED_UP(d,s,n);
+}
+static inline void __memcpy_aligned_dn (unsigned long d, unsigned long s,
+ long n)
+{
+ s += n;
+ d += n;
+ ALIGN_DEST_TO8_DN(d,s,n);
+ n -= 8;
+ while (n >= 0) {
+ unsigned long tmp;
+ s -= 8;
+ __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s));
+ n -= 8;
+ d -= 8;
+ *(unsigned long *) d = tmp;
+ }
+ n += 8;
+ DO_REST_ALIGNED_DN(d,s,n);
X }
X
X void * memcpy(void * dest, const void *src, size_t n)
X {
X if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) {
- __memcpy_aligned((unsigned long) dest, (unsigned long) src, n);
+ __memcpy_aligned_up ((unsigned long) dest, (unsigned long) src,
+ n);
X return dest;
X }
- __memcpy_unaligned((unsigned long) dest, (unsigned long) src, n);
+ __memcpy_unaligned_up ((unsigned long) dest, (unsigned long) src, n);
X return dest;
X }
X
X /* For backward modules compatibility, define __memcpy. */
X asm("__memcpy = memcpy; .globl __memcpy");
+
+void *memmove (void *dest, const void *src, size_t n)
+{
+ if (dest <= src) {
+ if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
+ __memcpy_aligned_up ((unsigned long) dest,
+ (unsigned long) src, n);
+ else
+ __memcpy_unaligned_up ((unsigned long) dest,
+ (unsigned long) src, n);
+ }
+ else {
+ if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
+ __memcpy_aligned_dn ((unsigned long) dest,
+ (unsigned long) src, n);
+ else
+ __memcpy_unaligned_dn ((unsigned long) dest,
+ (unsigned long) src, n);
+ }
+ return dest;
+}
diff -u --recursive --new-file v2.3.5/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c
--- v2.3.5/linux/arch/arm/kernel/ptrace.c Mon May 31 22:28:04 1999
+++ linux/arch/arm/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -164,25 +164,6 @@
X flush_tlb();
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm,addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.
diff -u --recursive --new-file v2.3.5/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.3.5/linux/arch/i386/Makefile Mon May 17 09:55:20 1999
+++ linux/arch/i386/Makefile Mon Jun 7 17:02:23 1999
@@ -67,6 +67,13 @@
X
X MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
X
+vmlinux: arch/i386/vmlinux.lds
+
+arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE
+ gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
+
+FORCE: ;
+
X zImage: vmlinux
X @$(MAKEBOOT) zImage
X
diff -u --recursive --new-file v2.3.5/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- v2.3.5/linux/arch/i386/boot/bootsect.S Wed Jun 24 14:30:08 1998
+++ linux/arch/i386/boot/bootsect.S Tue Jun 8 10:47:57 1999
@@ -58,12 +58,12 @@
X mov ds,ax
X mov ax,#INITSEG
X mov es,ax
- mov cx,#256
+ mov cx,#128
X sub si,si
X sub di,di
X cld
X rep
- movsw
+ movsd
X jmpi go,INITSEG
X
X ! ax and es already contain INITSEG
diff -u --recursive --new-file v2.3.5/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.5/linux/arch/i386/config.in Fri May 14 18:55:11 1999
+++ linux/arch/i386/config.in Mon Jun 7 17:02:23 1999
@@ -33,6 +33,10 @@
X define_bool CONFIG_X86_GOOD_APIC y
X fi
X
+choice 'Maximum Physical Memory' \
+ "1GB CONFIG_1GB \
+ 2GB CONFIG_2GB" 1GB
+
X bool 'Math emulation' CONFIG_MATH_EMULATION
X bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
X bool 'Symmetric multi-processing support' CONFIG_SMP
@@ -113,6 +117,8 @@
X fi
X
X endmenu
+
+source drivers/i2o/Config.in
X
X source drivers/pnp/Config.in
X
diff -u --recursive --new-file v2.3.5/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.5/linux/arch/i386/defconfig Wed Jun 2 14:44:39 1999
+++ linux/arch/i386/defconfig Mon Jun 7 22:12:01 1999
@@ -21,6 +21,8 @@
X CONFIG_X86_POPAD_OK=y
X CONFIG_X86_TSC=y
X CONFIG_X86_GOOD_APIC=y
+CONFIG_1GB=y
+# CONFIG_2GB is not set
X # CONFIG_MATH_EMULATION is not set
X # CONFIG_MTRR is not set
X CONFIG_SMP=y
@@ -58,6 +60,16 @@
X # CONFIG_APM is not set
X
X #
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
X # Plug and Play support
X #
X # CONFIG_PNP is not set
@@ -243,6 +255,11 @@
X # CONFIG_HAMRADIO is not set
X
X #
+# IrDA subsystem support
+#
+# CONFIG_IRDA is not set
+
+#
X # ISDN subsystem
X #
X # CONFIG_ISDN is not set
@@ -308,6 +325,7 @@
X # CONFIG_USB_AUDIO is not set
X # CONFIG_USB_ACM is not set
X # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCSI is not set
X
X #
X # Filesystems
diff -u --recursive --new-file v2.3.5/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.3.5/linux/arch/i386/kernel/mca.c Mon May 10 13:00:10 1999
+++ linux/arch/i386/kernel/mca.c Mon Jun 7 16:17:59 1999
@@ -112,21 +112,25 @@
X static ssize_t proc_mca_read(struct file*, char*, size_t, loff_t *);
X
X static struct file_operations proc_mca_operations = {
- NULL, /* array_lseek */
- proc_mca_read, /* array_read */
- NULL, /* array_write */
- NULL, /* array_readdir */
- NULL, /* array_poll */
- NULL, /* array_ioctl */
+ NULL, /* llseek */
+ proc_mca_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
X NULL, /* mmap */
- NULL, /* no special open code */
+ NULL, /* open */
X NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
+ NULL, /* release */
+ NULL, /* fsync */
+ NULL, /* fascync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL /* lock */
X };
X
X static struct inode_operations proc_mca_inode_operations = {
- &proc_mca_operations, /* default base directory file-ops */
+ &proc_mca_operations, /* default file-ops */
X NULL, /* create */
X NULL, /* lookup */
X NULL, /* link */
@@ -142,7 +146,10 @@
X NULL, /* writepage */
X NULL, /* bmap */
X NULL, /* truncate */
- NULL /* permission */
+ NULL, /* permission */
+ NULL, /* smap */
+ NULL, /* updatepage */
+ NULL /* revalidate */
X };
X #endif
X
@@ -220,18 +227,19 @@
X if(!MCA_bus)
X return;
X printk("Micro Channel bus detected.\n");
- save_flags(flags);
- cli();
X
X /* Allocate MCA_info structure (at address divisible by 8) */
X
- mca_info = kmalloc(sizeof(struct MCA_info), GFP_KERNEL);
+ mca_info = (struct MCA_info *)kmalloc(sizeof(struct MCA_info), GFP_KERNEL);
X
X if(mca_info == NULL) {
X printk("Failed to allocate memory for mca_info!");
- restore_flags(flags);
X return;
X }
+ memset(mca_info, 0, sizeof(struct MCA_info));
+
+ save_flags(flags);
+ cli();
X
X /* Make sure adapter setup is off */
X
@@ -705,12 +713,15 @@
X mca_info->slot[i].dev = 0;
X
X if(!mca_isadapter(i)) continue;
- node = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+
+ node = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
X
X if(node == NULL) {
X printk("Failed to allocate memory for MCA proc-entries!");
X return;
X }
+ memset(node, 0, sizeof(struct proc_dir_entry));
+
X if(i < MCA_MAX_SLOT_NR) {
X node->low_ino = PROC_MCA_SLOT + i;
X node->namelen = sprintf(mca_info->slot[i].procname,
@@ -854,7 +865,7 @@
X type = inode->i_ino;
X pid = type >> 16;
X type &= 0x0000ffff;
- start = 0;
+ start = NULL;
X dp = (struct proc_dir_entry *) inode->u.generic_ip;
X length = mca_fill((char *) page, pid, type,
X &start, ppos, count);
@@ -862,7 +873,7 @@
X free_page(page);
X return length;
X }
- if(start != 0) {
+ if(start != NULL) {
X /* We have had block-adjusting processing! */
X
X copy_to_user(buf, start, length);
diff -u --recursive --new-file v2.3.5/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.3.5/linux/arch/i386/kernel/ptrace.c Wed Mar 24 13:18:46 1999
+++ linux/arch/i386/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -172,25 +172,6 @@
X flush_tlb();
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm,addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.
diff -u --recursive --new-file v2.3.5/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.5/linux/arch/i386/kernel/setup.c Sat May 15 23:46:03 1999
+++ linux/arch/i386/kernel/setup.c Tue Jun 8 10:42:46 1999
@@ -12,6 +12,8 @@
X *
X * Force Centaur C6 processors to report MTRR capability.
X * Bart Hartgers <ba...@etpmod.phys.tue.nl>, May 199.
+ *
+ * Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
X */
X
X /*
@@ -688,7 +690,7 @@
X NULL, NULL, NULL, NULL }},
X { X86_VENDOR_INTEL, 6,
X { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)",
- NULL, "Pentium II (Deschutes)", "Celeron (Mendocino)", NULL,
+ NULL, "Pentium II (Deschutes)", "Mobile Pentium II", NULL,
X NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
X { X86_VENDOR_AMD, 4,
X { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB",
@@ -794,13 +796,19 @@
X if (c->x86_model <= 16)
X p = cpu_models[i].model_names[c->x86_model];
X
- /* Names for the Pentium II processors */
+ /* Names for the Pentium II Celeron processors
+ detectable only by also checking the cache size */
X if ((cpu_models[i].vendor == X86_VENDOR_INTEL)
- && (cpu_models[i].x86 == 6)
- && (c->x86_model == 5)
- && (c->x86_cache_size == 0)) {
- p = "Celeron (Covington)";
- }
+ && (cpu_models[i].x86 == 6)){
+ if(c->x86_model == 6 && c->x86_cache_size == 128) {
+ p = "Celeron (Mendocino)";
+ }
+ else {
+ if (c->x86_model == 5 && c->x86_cache_size == 0) {
+ p = "Celeron (Covington)";
+ }
+ }
+ }
X }
X
X }
diff -u --recursive --new-file v2.3.5/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.3.5/linux/arch/i386/kernel/signal.c Tue Dec 1 11:28:24 1998
+++ linux/arch/i386/kernel/signal.c Mon Jun 7 16:14:06 1999
@@ -698,6 +698,7 @@
X default:
X lock_kernel();
X sigaddset(&current->signal, signr);
+ recalc_sigpending(current);
X current->flags |= PF_SIGNALED;
X do_exit(exit_code);
X /* NOTREACHED */
diff -u --recursive --new-file v2.3.5/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.3.5/linux/arch/i386/mm/init.c Thu Jan 21 11:28:40 1999
+++ linux/arch/i386/mm/init.c Tue Jun 8 10:49:48 1999
@@ -390,6 +390,7 @@
X int datapages = 0;
X int initpages = 0;
X unsigned long tmp;
+ unsigned long endbase;
X
X end_mem &= PAGE_MASK;
X high_memory = (void *) end_mem;
@@ -417,8 +418,10 @@
X * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
X * They seem to have done something stupid with the floppy
X * controller as well..
+ * The amount of available base memory is in WORD 40:13.
X */
- while (start_low_mem < 0x9f000+PAGE_OFFSET) {
+ endbase = PAGE_OFFSET + ((*(unsigned short *)__va(0x413) * 1024) & PAGE_MASK);
+ while (start_low_mem < endbase) {
X clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
X start_low_mem += PAGE_SIZE;
X }
diff -u --recursive --new-file v2.3.5/linux/arch/i386/mm/ioremap.c linux/arch/i386/mm/ioremap.c
--- v2.3.5/linux/arch/i386/mm/ioremap.c Fri Nov 27 15:03:14 1998
+++ linux/arch/i386/mm/ioremap.c Thu Jun 3 14:17:51 1999
@@ -93,12 +93,17 @@
X {
X void * addr;
X struct vm_struct * area;
- unsigned long offset;
+ unsigned long offset, last_addr;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
X
X /*
X * Don't remap the low PCI/ISA area, it's always mapped..
X */
- if (phys_addr >= 0xA0000 && (phys_addr+size) <= 0x100000)
+ if (phys_addr >= 0xA0000 && last_addr < 0x100000)
X return phys_to_virt(phys_addr);
X
X /*
@@ -112,13 +117,7 @@
X */
X offset = phys_addr & ~PAGE_MASK;
X phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(size + offset);
-
- /*
- * Don't allow mappings that wrap..
- */
- if (!size || size > phys_addr + size)
- return NULL;
+ size = PAGE_ALIGN(last_addr) - phys_addr;
X
X /*
X * Ok, go for it..
diff -u --recursive --new-file v2.3.5/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- v2.3.5/linux/arch/i386/vmlinux.lds Sun Dec 27 22:45:13 1998
+++ linux/arch/i386/vmlinux.lds Tue Jun 8 23:03:37 1999
@@ -1,12 +1,12 @@
X /* ld script to make i386 Linux kernel
- * Written by Martin Mares <m...@atrey.karlin.mff.cuni.cz>
+ * Written by Martin Mares <m...@atrey.karlin.mff.cuni.cz>;
X */
X OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
X OUTPUT_ARCH(i386)
X ENTRY(_start)
X SECTIONS
X {
- . = 0xC0000000 + 0x100000;
+ . = 0xC0000000 + 0x100000;
X _text = .; /* Text and read-only data */
X .text : {
X *(.text)
diff -u --recursive --new-file v2.3.5/linux/arch/i386/vmlinux.lds.S linux/arch/i386/vmlinux.lds.S
--- v2.3.5/linux/arch/i386/vmlinux.lds.S Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/vmlinux.lds.S Mon Jun 7 17:02:23 1999
@@ -0,0 +1,69 @@
+/* ld script to make i386 Linux kernel
+ * Written by Martin Mares <m...@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+ . = PAGE_OFFSET_RAW + 0x100000;
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(.text)
+ *(.fixup)
+ *(.gnu.warning)
+ } = 0x9090
+ .text.lock : { *(.text.lock) } /* out-of-line lock text */
+ .rodata : { *(.rodata) }
+ .kstrtab : { *(.kstrtab) }
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ __start___ksymtab = .; /* Kernel symbol table */
+ __ksymtab : { *(__ksymtab) }
+ __stop___ksymtab = .;
+
+ _etext = .; /* End of text section */
+
+ .data : { /* Data */
+ *(.data)
+ CONSTRUCTORS
+ }
+
+ _edata = .; /* End of data section */
+
+ . = ALIGN(8192); /* init_task */
+ .data.init_task : { *(.data.init_task) }
+
+ . = ALIGN(4096); /* Init code and data */
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ . = ALIGN(4096);
+ .data.page_aligned : { *(.data.idt) }
+
+
+ __bss_start = .; /* BSS */
+ .bss : {
+ *(.bss)
+ }
+ _end = . ;
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+}
diff -u --recursive --new-file v2.3.5/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.3.5/linux/arch/m68k/kernel/ptrace.c Tue May 11 09:57:14 1999
+++ linux/arch/m68k/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -196,25 +196,6 @@
X flush_tlb_all();
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm, addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.
diff -u --recursive --new-file v2.3.5/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- v2.3.5/linux/arch/mips/kernel/irixelf.c Wed Nov 11 11:49:59 1998
+++ linux/arch/mips/kernel/irixelf.c Thu Jun 3 23:15:29 1999
@@ -132,9 +132,7 @@
X end = PAGE_ALIGN(end);
X if (end <= start)
X return;
- do_mmap(NULL, start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, 0);
+ do_brk(start, end - start);
X }
X
X
@@ -394,9 +392,7 @@
X
X /* Map the last of the bss segment */
X if (last_bss > len) {
- do_mmap(NULL, len, (last_bss - len),
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(len, (last_bss - len));
X }
X kfree(elf_phdata);
X
@@ -589,8 +585,7 @@
X unsigned long v;
X struct prda *pp;
X
- v = do_mmap (NULL, PRDA_ADDRESS, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, 0);
+ v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
X
X if (v < 0)
X return;
@@ -931,9 +926,7 @@
X len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
X bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
X if (bss > len)
- do_mmap(NULL, len, bss-len,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(len, bss-len);
X kfree(elf_phdata);
X return 0;
X }
diff -u --recursive --new-file v2.3.5/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v2.3.5/linux/arch/mips/kernel/ptrace.c Mon May 31 22:28:04 1999
+++ linux/arch/mips/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -143,25 +143,6 @@
X flush_tlb_page(vma, addr);
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm, addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.
diff -u --recursive --new-file v2.3.5/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.3.5/linux/arch/mips/kernel/sysirix.c Sat May 8 11:14:01 1999
+++ linux/arch/mips/kernel/sysirix.c Thu Jun 3 23:15:29 1999
@@ -571,7 +571,7 @@
X * Check against existing mmap mappings.
X */
X if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) {
- return -ENOMEM;
+ ret = -ENOMEM;
X goto out;
X }
X
@@ -579,7 +579,7 @@
X * Check if we have enough memory..
X */
X if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
- return -ENOMEM;
+ ret = -ENOMEM;
X goto out;
X }
X
@@ -587,10 +587,7 @@
X * Ok, looks good - let it rip.
X */
X mm->brk = brk;
- do_mmap(NULL, oldbrk, newbrk-oldbrk,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
-
+ do_brk(oldbrk, newbrk-oldbrk);
X ret = 0;
X
X out:
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.3.5/linux/arch/ppc/chrpboot/Makefile Mon May 31 22:28:04 1999
+++ linux/arch/ppc/chrpboot/Makefile Mon Jun 7 12:11:51 1999
@@ -17,7 +17,7 @@
X $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
X
X CFLAGS = -O -fno-builtin -DSTDC_HEADERS -I$(TOPDIR)/include
-LD_ARGS = -T ../vmlinux.lds -Ttext 0x00800000
+LD_ARGS = -Ttext 0x00400000
X OBJCOPY = $(CROSS_COMPILE)objcopy
X
X OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o # initrd.o
@@ -65,9 +65,10 @@
X initrd.o: ramdisk.image.gz piggyback
X ./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o
X
-zImage: $(OBJS) no_initrd.o
+zImage: $(OBJS) no_initrd.o mknote
X $(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
- objcopy zImage zImage
+ ./mknote > note
+ $(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
X
X zImage.initrd: $(OBJS) initrd.o
X $(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
@@ -92,8 +93,7 @@
X
X
X clean:
- rm -f piggyback
- rm -f $(OBJS) zImage
+ rm -f piggyback note mknote $(OBJS) zImage
X
X fastdep:
X $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- v2.3.5/linux/arch/ppc/chrpboot/main.c Wed Sep 30 10:14:16 1998
+++ linux/arch/ppc/chrpboot/main.c Mon Jun 7 12:11:51 1999
@@ -17,9 +17,9 @@
X #define get_32be(x) (*(unsigned *)(x))
X
X #define RAM_START 0x00000000
-#define RAM_END 0x00800000 /* only 8M mapped with BATs */
+#define RAM_END (8<<20)
X
-#define RAM_FREE 0x00540000 /* after image of chrpboot */
+#define RAM_FREE (6<<20) /* after image of chrpboot */
X #define PROG_START 0x00010000
X
X char *avail_ram;
@@ -38,16 +38,16 @@
X void *dst;
X unsigned char *im;
X unsigned initrd_start, initrd_size;
+ extern char _start;
X
- printf("chrpboot starting\n\r");
- /* setup_bats(); */
+ printf("chrpboot starting: loaded at 0x%x\n\r", &_start);
X
X if (initrd_len) {
X initrd_size = initrd_len;
X initrd_start = (RAM_END - initrd_size) & ~0xFFF;
X a1 = initrd_start;
X a2 = initrd_size;
- printf("initial ramdisk at %x (%u bytes)\n\r", initrd_start,
+ printf("initial ramdisk at 0x%x (%u bytes)\n\r", initrd_start,
X initrd_size);
X memcpy((char *)initrd_start, initrd_data, initrd_size);
X end_avail = (char *)initrd_start;
@@ -58,25 +58,19 @@
X dst = (void *) PROG_START;
X
X if (im[0] == 0x1f && im[1] == 0x8b) {
- void *cp = (void *) RAM_FREE;
- avail_ram = (void *) (RAM_FREE + ((len + 7) & -8));
- memcpy(cp, im, len);
- printf("gunzipping... ");
- gunzip(dst, 0x400000, cp, &len);
- printf("done\n\r");
-
+ avail_ram = (char *)RAM_FREE;
+ printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
+ gunzip(dst, 0x400000, im, &len);
+ printf("done %u bytes\n\r", len);
X } else {
X memmove(dst, im, len);
X }
X
X flush_cache(dst, len);
-
- sa = PROG_START+12;
+
+ sa = *(unsigned long *)PROG_START+PROG_START;
X printf("start address = 0x%x\n\r", sa);
X
-#if 0
- pause();
-#endif
X (*(void (*)())sa)(a1, a2, prom, 0, 0);
X
X printf("returned?\n\r");
@@ -150,7 +144,7 @@
X s.avail_out = dstlen;
X r = inflate(&s, Z_FINISH);
X if (r != Z_OK && r != Z_STREAM_END) {
- printf("inflate returned %d\n\r", r);
+ printf("inflate returned %d msg: %s\n\r", r, s.msg);
X exit();
X }
X *lenp = s.next_out - (unsigned char *) dst;
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/chrpboot/mknote.c linux/arch/ppc/chrpboot/mknote.c
--- v2.3.5/linux/arch/ppc/chrpboot/mknote.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/chrpboot/mknote.c Mon Jun 7 12:11:51 1999
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Cort Dougan 1999.
+ *
+ * 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.
+ *
+ * Generate a note section as per the CHRP specification.
+ *
+ */
+
+#include <stdio.h>
+
+#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
+
+int main(void)
+{
+/* header */
+ /* namesz */
+ PL(strlen("PowerPC")+1);
+ /* descrsz */
+ PL(6*4);
+ /* type */
+ PL(0x1275);
+ /* name */
+ printf("PowerPC"); printf("%c", 0);
+
+/* descriptor */
+ /* real-mode */
+ PL(0xffffffff);
+ /* real-base */
+ PL(0x00c00000);
+ /* real-size */
+ PL(0xffffffff);
+ /* virt-base */
+ PL(0xffffffff);
+ /* virt-size */
+ PL(0xffffffff);
+ /* load-base */
+ PL(0x4000);
+ return 0;
+}
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/coffboot/zlib.c linux/arch/ppc/coffboot/zlib.c
--- v2.3.5/linux/arch/ppc/coffboot/zlib.c Wed Sep 30 10:14:16 1998
+++ linux/arch/ppc/coffboot/zlib.c Mon Jun 7 12:11:51 1999
@@ -11,7 +11,7 @@
X * - added Z_PACKET_FLUSH (see zlib.h for details)
X * - added inflateIncomp
X *
- * $Id: zlib.c,v 1.2 1998/09/03 17:40:53 cort Exp $
+ * $Id: zlib.c,v 1.3 1999/05/27 22:22:54 cort Exp $
X */
X
X /*+++++*/
@@ -649,6 +649,11 @@
X /* load local pointers */
X #define LOAD {LOADIN LOADOUT}
X
+/*
+ * The IBM 150 firmware munges the data right after _etext[]. This
+ * protects it. -- Cort
+ */
+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
X /* And'ing with mask[n] masks the lower n bits */
X local uInt inflate_mask[] = {
X 0x0000,
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.3.5/linux/arch/ppc/common_defconfig Mon May 31 22:28:04 1999
+++ linux/arch/ppc/common_defconfig Mon Jun 7 12:11:51 1999
@@ -9,14 +9,13 @@
X CONFIG_6xx=y
X # CONFIG_PPC64 is not set
X # CONFIG_8xx is not set
-CONFIG_PMAC=y
+# CONFIG_PMAC is not set
X # CONFIG_PREP is not set
X # CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
+CONFIG_ALL_PPC=y
X # CONFIG_APUS is not set
X # CONFIG_MBX is not set
X # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
X CONFIG_6xx=y
X
X #
@@ -51,6 +50,7 @@
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
@@ -60,7 +60,7 @@
X #
X # Block devices
X #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
X CONFIG_BLK_DEV_IDE=y
X
X #
@@ -77,7 +77,7 @@
X # CONFIG_BLK_DEV_CMD640 is not set
X # CONFIG_BLK_DEV_RZ1000 is not set
X # CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_SL82C105=y
X CONFIG_BLK_DEV_IDE_PMAC=y
X CONFIG_BLK_DEV_IDEDMA_PMAC=y
X CONFIG_BLK_DEV_IDEDMA=y
@@ -117,7 +117,7 @@
X # CONFIG_NET_IPGRE is not set
X # CONFIG_IP_MROUTE is not set
X CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
+CONFIG_SYN_COOKIES=y
X
X #
X # (it is safe to leave these untouched)
@@ -199,7 +199,14 @@
X # CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
X # CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+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_PQS_PDS 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
@@ -237,7 +244,7 @@
X # CONFIG_ACENIC is not set
X # CONFIG_NET_ISA is not set
X CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
+CONFIG_PCNET32=y
X # CONFIG_AC3200 is not set
X # CONFIG_APRICOT is not set
X # CONFIG_CS89x0 is not set
@@ -297,12 +304,16 @@
X CONFIG_FB_CONTROL=y
X CONFIG_FB_PLATINUM=y
X CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
X CONFIG_FB_IMSTT=y
X CONFIG_FB_CT65550=y
X # CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+# CONFIG_FB_MATROX_MILLENIUM is not set
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G100 is not set
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
X # CONFIG_FB_VIRTUAL is not set
X # CONFIG_FBCON_ADVANCED is not set
X CONFIG_FBCON_CFB8=y
@@ -324,12 +335,22 @@
X #
X CONFIG_VT=y
X CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
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 is not set
+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
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
X CONFIG_NVRAM=y
@@ -448,7 +469,34 @@
X # CONFIG_SOUND_SONICVIBES is not set
X # CONFIG_SOUND_MSNDCLAS is not set
X # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+CONFIG_SOUND_CS4232=m
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
X
X #
X # Kernel hacking
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.5/linux/arch/ppc/config.in Mon May 31 22:28:04 1999
+++ linux/arch/ppc/config.in Tue Jun 8 10:52:26 1999
@@ -176,6 +176,7 @@
X endmenu
X
X source drivers/char/Config.in
+source drivers/usb/Config.in
X source fs/Config.in
X
X mainmenu_option next_comment
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.5/linux/arch/ppc/defconfig Mon May 31 22:28:04 1999
+++ linux/arch/ppc/defconfig Mon Jun 7 12:11:51 1999
@@ -9,14 +9,13 @@
X CONFIG_6xx=y
X # CONFIG_PPC64 is not set
X # CONFIG_8xx is not set
-CONFIG_PMAC=y
+# CONFIG_PMAC is not set
X # CONFIG_PREP is not set
X # CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
+CONFIG_ALL_PPC=y
X # CONFIG_APUS is not set
X # CONFIG_MBX is not set
X # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
X CONFIG_6xx=y
X
X #
@@ -51,6 +50,7 @@
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
@@ -60,7 +60,7 @@
X #
X # Block devices
X #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
X CONFIG_BLK_DEV_IDE=y
X
X #
@@ -77,7 +77,7 @@
X # CONFIG_BLK_DEV_CMD640 is not set
X # CONFIG_BLK_DEV_RZ1000 is not set
X # CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_SL82C105=y
X CONFIG_BLK_DEV_IDE_PMAC=y
X CONFIG_BLK_DEV_IDEDMA_PMAC=y
X CONFIG_BLK_DEV_IDEDMA=y
@@ -117,7 +117,7 @@
X # CONFIG_NET_IPGRE is not set
X # CONFIG_IP_MROUTE is not set
X CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
+CONFIG_SYN_COOKIES=y
X
X #
X # (it is safe to leave these untouched)
@@ -199,7 +199,14 @@
X # CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
X # CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+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_PQS_PDS 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
@@ -237,7 +244,7 @@
X # CONFIG_ACENIC is not set
X # CONFIG_NET_ISA is not set
X CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
+CONFIG_PCNET32=y
X # CONFIG_AC3200 is not set
X # CONFIG_APRICOT is not set
X # CONFIG_CS89x0 is not set
@@ -297,12 +304,16 @@
X CONFIG_FB_CONTROL=y
X CONFIG_FB_PLATINUM=y
X CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
X CONFIG_FB_IMSTT=y
X CONFIG_FB_CT65550=y
X # CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+# CONFIG_FB_MATROX_MILLENIUM is not set
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G100 is not set
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
X # CONFIG_FB_VIRTUAL is not set
X # CONFIG_FBCON_ADVANCED is not set
X CONFIG_FBCON_CFB8=y
@@ -324,12 +335,22 @@
X #
X CONFIG_VT=y
X CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
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 is not set
+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
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
X CONFIG_NVRAM=y
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.3.5/linux/arch/ppc/kernel/chrp_pci.c Mon May 31 22:28:04 1999
+++ linux/arch/ppc/kernel/chrp_pci.c Mon Jun 7 12:11:51 1999
@@ -167,6 +167,62 @@
X return PCIBIOS_SUCCESSFUL;
X }
X
+
+int rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
+{
+ unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+ if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 1 ) != 0 )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
+{
+ unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+ if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 2 ) != 0 )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
+{
+ unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+ if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 4 ) != 0 )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
+{
+ unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+ if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 1, (ulong)val ) != 0 )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
+{
+ unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+ if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 2, (ulong)val ) != 0 )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
+{
+ unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
+ if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 4, (ulong)val ) != 0 )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+
X /*
X * Temporary fixes for PCI devices. These should be replaced by OF query
X * code -- Geert
@@ -256,6 +312,7 @@
X
X decl_config_access_method(grackle);
X decl_config_access_method(indirect);
+decl_config_access_method(rtas);
X
X void __init
X chrp_setup_pci_ptrs(void)
@@ -276,7 +333,7 @@
X {
X /* find out how many pythons */
X while ( (py = py->next) ) python_busnr++;
- set_config_access_method(python);
+ set_config_access_method(python);
X /*
X * We base these values on the machine type but should
X * try to read them from the python controller itself.
@@ -297,10 +354,22 @@
X }
X else
X {
- pci_dram_offset = 0;
- isa_mem_base = 0xf7000000;
- isa_io_base = 0xf8000000;
- set_config_access_method(gg2);
+ if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) )
+ {
+ pci_dram_offset = 0;
+ isa_mem_base = 0x80000000;
+ isa_io_base = 0xfe000000;
+ pci_config_address = (unsigned int *)0xfec00000;
+ pci_config_data = (unsigned char *)0xfee00000;
+ set_config_access_method(indirect);
+ }
+ else
+ {
+ pci_dram_offset = 0;
+ isa_mem_base = 0xf7000000;
+ isa_io_base = 0xf8000000;
+ set_config_access_method(gg2);
+ }
X }
X }
X
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.5/linux/arch/ppc/kernel/chrp_setup.c Mon May 31 22:28:04 1999
+++ linux/arch/ppc/kernel/chrp_setup.c Mon Jun 7 12:11:51 1999
@@ -32,6 +32,7 @@
X #include <linux/console.h>
X #include <linux/pci.h>
X #include <linux/openpic.h>
+#include <linux/version.h>
X
X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -65,6 +66,7 @@
X
X unsigned long chrp_get_rtc_time(void);
X int chrp_set_rtc_time(unsigned long nowtime);
+unsigned long rtas_event_scan_rate = 0, rtas_event_scan_ct = 0;
X void chrp_calibrate_decr(void);
X void chrp_time_init(void);
X
@@ -235,6 +237,7 @@
X chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
X {
X extern char cmd_line[];
+ struct device_node *device;
X
X /* init to some ~sane value until calibrate_delay() runs */
X loops_per_sec = 50000000;
@@ -274,57 +277,73 @@
X find_path_device("/"), "platform-open-pic", NULL);
X OpenPIC = ioremap((unsigned long)OpenPIC, sizeof(struct OpenPIC));
X }
-
+
X /*
X * Fix the Super I/O configuration
X */
- sio_init();
+ /*sio_init();*/
X #ifdef CONFIG_DUMMY_CONSOLE
X conswitchp = &dummy_con;
X #endif
- /* my starmax 6000 needs this but the longtrail shouldn't do it -- Cort */
- if ( !strncmp("MOT", get_property(find_path_device("/"),
- "model", NULL),3) )
- *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+
+ /* Get the event scan rate for the rtas so we know how
+ * often it expects a heartbeat. -- Cort
+ */
+ if ( rtas_data )
+ {
+ struct property *p;
+ device = find_devices("rtas");
+ for ( p = device->properties;
+ strncmp(p->name, "rtas-event-scan-rate", 20) && p ;
+ p = p->next )
+ /* nothing */ ;
+ if ( p && *(unsigned long *)p->value )
+ {
+ rtas_event_scan_rate = (HZ/(*(unsigned long *)p->value)*30)-1;
+ rtas_event_scan_ct = 1;
+ printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
+ *(unsigned long *)p->value, rtas_event_scan_rate );
+ }
+ }
X }
X
X void
+chrp_event_scan(void)
+{
+ unsigned char log[1024];
+ if ( rtas_event_scan_rate && (rtas_event_scan_ct-- <= 0) )
+ {
+ call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 );
+ rtas_event_scan_ct = rtas_event_scan_rate;
+ }
+}
+
+void
X chrp_restart(char *cmd)
X {
-#if 0
- extern unsigned int rtas_entry, rtas_data, rtas_size;
X printk("RTAS system-reboot returned %d\n",
X call_rtas("system-reboot", 0, 1, NULL));
- printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
- rtas_entry,rtas_data,rtas_size);
X for (;;);
-#else
- printk("System Halted\n");
- while(1);
-#endif
X }
X
X void
X chrp_power_off(void)
X {
- /* RTAS doesn't seem to work on Longtrail.
- For now, do it the same way as the PReP. */
-#if 0
- extern unsigned int rtas_entry, rtas_data, rtas_size;
+ /* allow power on only with power button press */
+#define PWR_FIELD(x) (0x8000000000000000 >> ((x)-96))
X printk("RTAS power-off returned %d\n",
- call_rtas("power-off", 2, 1, NULL, 0, 0));
- printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
- rtas_entry,rtas_data,rtas_size);
+ call_rtas("power-off", 2, 1, NULL,
+ ((PWR_FIELD(96)|PWR_FIELD(97))>>32)&0xffffffff,
+ (PWR_FIELD(96)|PWR_FIELD(97))&0xffffffff));
+#undef PWR_FIELD
X for (;;);
-#else
- chrp_restart(NULL);
-#endif
X }
X
X void
X chrp_halt(void)
X {
- chrp_restart(NULL);
+ chrp_power_off();
X }
X
X u_int
@@ -653,5 +672,21 @@
X ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
X
X ppc_ide_md.io_base = _IO_BASE;
-#endif
+#endif
+ /*
+ * Print the banner, then scroll down so boot progress
+ * can be printed. -- Cort
+ */
+ chrp_progress("Linux/PPC "UTS_RELEASE"\n");
+}
+
+void chrp_progress(char *s)
+{
+ extern unsigned int rtas_data;
+
+ if ( (_machine != _MACH_chrp) || !rtas_data )
+ return;
+ call_rtas( "display-character", 1, 1, NULL, '\r' );
+ while ( *s )
+ call_rtas( "display-character", 1, 1, NULL, *s++ );
X }
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.5/linux/arch/ppc/kernel/head.S Mon May 31 22:28:04 1999
+++ linux/arch/ppc/kernel/head.S Mon Jun 7 12:11:51 1999
@@ -1,7 +1,7 @@
X /*
X * arch/ppc/kernel/head.S
X *
- * $Id: head.S,v 1.131 1999/05/14 22:37:21 cort Exp $
+ * $Id: head.S,v 1.133 1999/05/20 05:13:08 cort Exp $
X *
X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)
@@ -2615,7 +2615,6 @@
X */
X .globl enter_rtas
X enter_rtas:
- stwu r1,-16(r1)
X mflr r0
X stw r0,20(r1)
X lis r4,rtas_data@ha
@@ -2636,7 +2635,6 @@
X andi. r9,r9,MSR_ME|MSR_RI
X sync /* disable interrupts so SRR0/1 */
X mtmsr r0 /* don't get trashed */
- li r6,0
X mtlr r6
X mtspr SPRG2,r7
X mtspr SRR0,r8
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.3.5/linux/arch/ppc/kernel/idle.c Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/idle.c Mon Jun 7 12:11:51 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: idle.c,v 1.61 1999/03/18 04:15:45 cort Exp $
+ * $Id: idle.c,v 1.62 1999/05/24 05:43:18 cort Exp $
X *
X * Idle daemon for PowerPC. Idle daemon will handle any action
X * that needs to be taken when the system becomes idle.
@@ -50,6 +50,7 @@
X /* endless loop with no priority at all */
X current->priority = 0;
X current->counter = -100;
+ init_idle();
X for (;;)
X {
X __sti();
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.3.5/linux/arch/ppc/kernel/irq.c Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/irq.c Mon Jun 7 12:11:51 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: irq.c,v 1.105 1999/03/25 19:51:51 cort Exp $
+ * $Id: irq.c,v 1.106 1999/05/25 21:16:04 cort Exp $
X *
X * arch/ppc/kernel/irq.c
X *
@@ -65,7 +65,6 @@
X void enable_irq(unsigned int irq_nr);
X void disable_irq(unsigned int irq_nr);
X
-/* Fixme - Need to figure out a way to get rid of this - Corey */
X volatile unsigned char *chrp_int_ack_special;
X
X #ifdef CONFIG_APUS
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.3.5/linux/arch/ppc/kernel/misc.S Mon May 31 22:28:04 1999
+++ linux/arch/ppc/kernel/misc.S Mon Jun 7 12:11:51 1999
@@ -866,7 +866,11 @@
X .long sys_getresuid /* 165 */
SHAR_EOF
true || echo 'restore of patch-2.3.6 failed'
fi
echo 'End of part 01'
echo 'File patch-2.3.6 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part02

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


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

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


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

X .long sys_query_module
X .long sys_poll
+#ifdef CONFIG_NFS
X .long sys_nfsservctl
+#else
+ .long sys_ni_syscall
+#endif
X .long sys_setresgid
X .long sys_getresgid /* 170 */
X .long sys_prctl
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.3.5/linux/arch/ppc/kernel/prom.c Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/prom.c Mon Jun 7 12:11:51 1999


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

- * $Id: prom.c,v 1.54 1999/05/10 04:43:46 cort Exp $
+ * $Id: prom.c,v 1.60 1999/05/25 01:42:41 cort Exp $
X *
X * Procedures for interfacing to the Open Firmware PROM on
X * Power Macintosh computers.
@@ -24,6 +24,7 @@
X #include <asm/io.h>
X #include <asm/smp.h>
X #include <asm/bootx.h>
+#include <asm/system.h>
X
X /*
X * Properties whose value is longer than this get excluded from our
@@ -412,6 +413,9 @@
X mem = copy_device_tree(mem, mem + (1<<20));
X prom_print(RELOC("done\n"));
X
+
+ RELOC(klimit) = (char *) (mem - offset);
+
X prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
X if (prom_rtas != (void *) -1) {
X RELOC(rtas_size) = 0;
@@ -421,9 +425,19 @@
X if (RELOC(rtas_size) == 0) {
X RELOC(rtas_data) = 0;
X } else {
- mem = (mem + 4095) & -4096; /* round to page bdry */
+ /*
+ * We do _not_ want the rtas_data inside the klimit
+ * boundry since it'll be squashed when we do the
+ * relocate of the kernel on chrp right after prom_init()
+ * in head.S. So, we just pick a spot in memory.
+ * -- Cort
+ */
+#if 0
+ mem = (mem + 4095) & -4096;
X RELOC(rtas_data) = mem + KERNELBASE;
X mem += RELOC(rtas_size);
+#endif
+ RELOC(rtas_data) = (6<<20) + KERNELBASE;
X }
X prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
X {
@@ -448,7 +462,7 @@
X else
X prom_print(RELOC(" done\n"));
X }
- RELOC(klimit) = (char *) (mem - offset);
+
X #ifdef CONFIG_SMP
X /*
X * With CHRP SMP we need to use the OF to start the other
@@ -1289,7 +1303,7 @@
X unsigned long *outputs, ...)
X {
X va_list list;
- int i;
+ int i, s;
X struct device_node *rtas;
X int *tokp;
X union {
@@ -1305,16 +1319,19 @@
X printk(KERN_ERR "No RTAS service called %s\n", service);
X return -1;
X }
- u.words[0] = __pa(*tokp);
+ u.words[0] = *tokp;
X u.words[1] = nargs;
X u.words[2] = nret;
X va_start(list, outputs);
X for (i = 0; i < nargs; ++i)
X u.words[i+3] = va_arg(list, unsigned long);
X va_end(list);
+
+ s = _disable_interrupts();
X spin_lock(&rtas_lock);
X enter_rtas((void *)__pa(&u));
X spin_unlock(&rtas_lock);
+ _enable_interrupts(s);
X if (nret > 1 && outputs != NULL)
X for (i = 0; i < nret-1; ++i)
X outputs[i] = u.words[i+nargs+4];
@@ -1326,8 +1343,7 @@
X abort()
X {
X #ifdef CONFIG_XMON
- extern void xmon(void *);
- xmon(0);
+ xmon(NULL);
X #endif
X prom_exit();
X }
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.3.5/linux/arch/ppc/kernel/ptrace.c Mon May 31 22:28:04 1999
+++ linux/arch/ppc/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -190,25 +190,6 @@


X flush_tlb_all();
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;

- vma = find_vma(tsk->mm,addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.

diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.3.5/linux/arch/ppc/kernel/smp.c Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/smp.c Mon Jun 7 12:11:51 1999


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

- * $Id: smp.c,v 1.49 1999/03/18 04:16:31 cort Exp $
+ * $Id: smp.c,v 1.52 1999/05/23 22:43:51 cort Exp $
X *
X * Smp support for ppc.
X *
@@ -388,9 +388,12 @@
X
X void __init smp_callin(void)
X {
+ int i;
+
X printk("SMP %d: smp_callin()\n",current->processor);
X smp_store_cpu_info(current->processor);
X set_dec(decrementer_count);
+
X #if 0
X current->mm->mmap->vm_page_prot = PAGE_SHARED;
X current->mm->mmap->vm_start = PAGE_OFFSET;
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.3.5/linux/arch/ppc/kernel/syscalls.c Mon May 31 22:28:04 1999
+++ linux/arch/ppc/kernel/syscalls.c Mon Jun 7 12:11:51 1999
@@ -182,18 +182,14 @@
X int fd[2];
X int error;
X
- error = verify_area(VERIFY_WRITE, fildes, 8);
- if (error)
- return error;
X lock_kernel();
X error = do_pipe(fd);
X unlock_kernel();
- if (error)
- return error;
- if (__put_user(fd[0],0+fildes)
- || __put_user(fd[1],1+fildes))
- return -EFAULT; /* should we close the fds? */
- return 0;
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
X }
X
X asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.3.5/linux/arch/ppc/kernel/time.c Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/time.c Mon Jun 7 12:11:51 1999


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

- * $Id: time.c,v 1.47 1999/03/18 05:11:11 cort Exp $
+ * $Id: time.c,v 1.48 1999/05/22 19:35:57 cort Exp $
X * Common time routines among all ppc machines.
X *
X * Written by Cort Dougan (co...@cs.nmt.edu) to merge
@@ -126,13 +126,17 @@
X smp_local_timer_interrupt(regs);
X #endif
X
- /* Fixme - make this more generic - Corey */
X #ifdef CONFIG_APUS
X {
X extern void apus_heartbeat (void);
X apus_heartbeat ();
X }
X #endif
+#if defined(CONFIG_ALL_PPC) || defined(CONFIG_CHRP)
+ if ( _machine == _MACH_chrp )
+ chrp_event_scan();
+#endif
+
X hardirq_exit(cpu);
X }
X
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.5/linux/arch/ppc/mm/init.c Mon May 31 22:28:04 1999
+++ linux/arch/ppc/mm/init.c Mon Jun 7 12:11:51 1999


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

- * $Id: init.c,v 1.165 1999/05/14 22:37:29 cort Exp $
+ * $Id: init.c,v 1.166 1999/05/22 18:18:30 cort Exp $


X *
X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)

@@ -402,7 +402,7 @@
X for (i = 0; i < size; i += PAGE_SIZE)
X map_page(&init_task, v+i, p+i, flags);
X out:
- return (void *) (v + (p & ~PAGE_MASK));
+ return (void *) (v + (addr & ~PAGE_MASK));
X }
X
X void iounmap(void *addr)
diff -u --recursive --new-file v2.3.5/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.3.5/linux/arch/ppc/xmon/xmon.c Mon May 31 22:28:04 1999
+++ linux/arch/ppc/xmon/xmon.c Mon Jun 7 12:11:51 1999
@@ -999,7 +999,7 @@
X int c;
X
X c = inchar();
- if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
+ if ((isxdigit(c) && (c != 'f') && (c != 'd')) || (c == '\n'))
X termch = c;
X scanhex(&adrs);
X if( termch != '\n')
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/Makefile linux/arch/sparc/Makefile
--- v2.3.5/linux/arch/sparc/Makefile Sun Oct 4 10:22:42 1998
+++ linux/arch/sparc/Makefile Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.39 1998/09/16 12:31:31 jj Exp $
+# $Id: Makefile,v 1.41 1999/06/04 13:29:05 jj Exp $
X # sparc/Makefile
X #
X # Makefile for the architecture dependent flags and dependencies on the
@@ -15,7 +15,7 @@
X # Uncomment the first CFLAGS if you are doing kgdb source level
X # debugging of the kernel to get the proper debugging information.
X
-IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi)
+IS_EGCS := $(shell if $(CC) -c -m32 -o _tmp.o arch/sparc/math-emu/fnegs.c >/dev/null 2>&1; then echo y; else echo n; fi; rm -f _tmp.o)
X NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
X
X ifeq ($(NEW_GAS),y)
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- v2.3.5/linux/arch/sparc/kernel/ebus.c Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc/kernel/ebus.c Wed Jun 9 14:44:25 1999
@@ -1,9 +1,10 @@
-/* $Id: ebus.c,v 1.2 1998/10/07 11:35:16 jj Exp $
+/* $Id: ebus.c,v 1.3 1999/06/03 15:02:09 davem Exp $
X * ebus.c: PCI to EBus bridge device.
X *
X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)
X *
X * Adopted for sparc by V. Roganov and G. Raiko.
+ * Fixes for different platforms by Pete Zaitcev.
X */
X
X #include <linux/config.h>
@@ -25,9 +26,9 @@
X #undef DEBUG_FILL_EBUS_DEV
X
X #ifdef PROM_DEBUG
-#define dprintf prom_printf
+#define dprintk prom_printf
X #else
-#define dprintf printk
+#define dprintk printk
X #endif
X
X struct linux_ebus *ebus_chain = 0;
@@ -48,6 +49,9 @@
X extern int envctrl_init(void);
X #endif
X
+/* We are together with pcic.c under CONFIG_PCI. */
+extern unsigned int pcic_pin_to_irq(unsigned int, char *name);
+
X static inline unsigned long ebus_alloc(size_t size)
X {
X return (unsigned long)kmalloc(size, GFP_ATOMIC);
@@ -66,6 +70,7 @@
X strcpy(dev->prom_name, lbuf);
X
X len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+ if (len == -1) len = 0;
X dev->num_addrs = len / sizeof(regs[0]);
X
X for (i = 0; i < dev->num_addrs; i++) {
@@ -77,22 +82,36 @@
X dev->base_address[i] = dev->parent->base_address[regs[i]];
X }
X
+ /*
+ * Houston, we have a problem...
+ * Sometimes PROM supplies absolutely meaningless properties.
+ * Still, we take what it gives since we have nothing better.
+ * Children of ebus may be wired on any input pin of PCIC.
+ */
X len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
X if ((len == -1) || (len == 0)) {
X dev->num_irqs = 0;
- /*
- * Oh, well, some PROMs don't export interrupts
- * property to children of EBus devices...
- *
- * Be smart about PS/2 keyboard and mouse.
- */
- if (!strcmp(dev->parent->prom_name, "8042")) {
+ dev->irqs[0] = 0;
+ if (dev->parent->num_irqs != 0) {
X dev->num_irqs = 1;
X dev->irqs[0] = dev->parent->irqs[0];
+/* P3 remove */ printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]);
X }
X } else {
X dev->num_irqs = len / sizeof(irqs[0]);
- printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]);
+ if (irqs[0] == 0 || irqs[0] >= 8) {
+ /*
+ * XXX Zero is a valid pin number...
+ * This works as long as Ebus is not wired to INTA#.
+ */
+ printk("EBUS: %s got bad irq %d from PROM\n",
+ dev->prom_name, irqs[0]);
+ dev->num_irqs = 0;
+ dev->irqs[0] = 0;
+ } else {
+ dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+/* P3 remove */ printk("EBUS: dev %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]);
+ }
X }
X
X #ifdef DEBUG_FILL_EBUS_DEV
@@ -131,7 +150,30 @@
X dev->num_addrs = len / sizeof(struct linux_prom_registers);
X
X for (i = 0; i < dev->num_addrs; i++) {
- n = (regs[i].which_io - 0x10) >> 2;
+ /*
+ * XXX Collect JE-1 PROM
+ *
+ * Example - JS-E with 3.11:
+ * /ebus
+ * regs
+ * 0x00000000, 0x0, 0x00000000, 0x0, 0x00000000,
+ * 0x82000010, 0x0, 0xf0000000, 0x0, 0x01000000,
+ * 0x82000014, 0x0, 0x38800000, 0x0, 0x00800000,
+ * ranges
+ * 0x00, 0x00000000, 0x02000010, 0x0, 0x0, 0x01000000,
+ * 0x01, 0x01000000, 0x02000014, 0x0, 0x0, 0x00800000,
+ * /ebus/8042
+ * regs
+ * 0x00000001, 0x00300060, 0x00000008,
+ * 0x00000001, 0x00300060, 0x00000008,
+ */
+ n = regs[i].which_io;
+ if (n >= 4) {
+ /* XXX This is copied from old JE-1 by Gleb. */
+ n = (regs[i].which_io - 0x10) >> 2;
+ } else {
+ ;
+ }
X
X dev->base_address[i] = dev->bus->self->base_address[n];
X dev->base_address[i] += regs[i].phys_addr;
@@ -141,8 +183,14 @@
X (unsigned long)sparc_alloc_io (dev->base_address[i], 0,
X regs[i].reg_size,
X dev->prom_name, 0, 0);
+#if 0
+/*
+ * This release_region() screwes those who do sparc_alloc_io().
+ * Change drivers which do check_region(). See drivers/block/floppy.c.
+ */
X /* Some drivers call 'check_region', so we release it */
X release_region(dev->base_address[i] & PAGE_MASK, PAGE_SIZE);
+#endif
X
X if (dev->base_address[i] == 0 ) {
X panic("ebus: unable sparc_alloc_io for dev %s",
@@ -154,12 +202,22 @@
X len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
X if ((len == -1) || (len == 0)) {
X dev->num_irqs = 0;
+ if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
+ dev->num_irqs = 1;
+/* P3 remove */ printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]);
+ }
X } else {
- dev->num_irqs = len / sizeof(irqs[0]);
-
-#define IRQ_8042 7
- if (irqs[0] == 4) dev->irqs[0] = IRQ_8042;
- printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]);
+ dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */
+ if (irqs[0] == 0 || irqs[0] >= 8) {
+ /* See above for the parent. XXX */
+ printk("EBUS: %s got bad irq %d from PROM\n",
+ dev->prom_name, irqs[0]);
+ dev->num_irqs = 0;
+ dev->irqs[0] = 0;
+ } else {
+ dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+/* P3 remove */ printk("EBUS: child %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]);
+ }
X }
X
X #ifdef DEBUG_FILL_EBUS_DEV
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.3.5/linux/arch/sparc/kernel/entry.S Tue May 11 08:24:31 1999
+++ linux/arch/sparc/kernel/entry.S Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.159 1999/05/08 03:00:03 davem Exp $
+/* $Id: entry.S,v 1.160 1999/06/03 15:02:11 davem Exp $
X * arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -1888,5 +1888,53 @@
X LOAD_CURRENT(g6, o0)
X retl
X nop
+
+#ifdef CONFIG_PCI
+#include <asm/pcic.h>
+
+ .align 4
+ .globl linux_trap_ipi15_pcic
+linux_trap_ipi15_pcic:
+ rd %wim, %l3
+ SAVE_ALL
+
+ /*
+ * First deactivate NMI
+ * or we cannot drop ET, cannot get window spill traps.
+ * The busy loop is necessary because the PIO error
+ * sometimes does not go away quickly and we trap again.
+ */
+ sethi %hi(C_LABEL(pcic_regs)), %o1
+ ld [%o1 + %lo(C_LABEL(pcic_regs))], %o2
+
+ ! Get pending status for printouts later.
+ ld [%o2 + PCI_SYS_INT_PENDING], %o0
+
+ mov PCI_SYS_INT_PENDING_CLEAR_ALL, %o1
+ stb %o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR]
+1:
+ ld [%o2 + PCI_SYS_INT_PENDING], %o1
+ andcc %o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0
+ bne 1b
+ nop
+
+ or %l0, PSR_PIL, %l4
+ wr %l4, 0x0, %psr
+ WRITE_PAUSE
+ wr %l4, PSR_ET, %psr
+ WRITE_PAUSE
+
+ call C_LABEL(pcic_nmi)
+ add %sp, REGWIN_SZ, %o1 ! struct pt_regs *regs
+ RESTORE_ALL
+
+ .globl C_LABEL(pcic_nmi_trap_patch)
+C_LABEL(pcic_nmi_trap_patch):
+ sethi %hi(linux_trap_ipi15_pcic), %l3
+ jmpl %l3 + %lo(linux_trap_ipi15_pcic), %g0
+ rd %psr, %l0
+ .word 0
+
+#endif /* CONFIG_PCI */
X
X /* End of entry.S */
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.3.5/linux/arch/sparc/kernel/head.S Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/kernel/head.S Wed Jun 9 14:44:25 1999
@@ -1,11 +1,13 @@
-/* $Id: head.S,v 1.95 1999/04/13 07:40:34 anton Exp $
+/* $Id: head.S,v 1.96 1999/06/03 15:02:15 davem Exp $
X * head.S: The initial boot code for the Sparc port of Linux.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1995 Peter Zaitcev (Zai...@ipmce.su)
+ * Copyright (C) 1995,1999 Pete Zaitcev (zai...@metabyte.com)
X * Copyright (C) 1996 Miguel de Icaza (mig...@nuclecu.unam.mx)
X * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
X * Copyright (C) 1997 Michael A. Griffith (gr...@acm.org)
+ *
+ * CompactPCI platform by Eric Brower, 1999.
X */
X
X #include <linux/version.h>
@@ -116,10 +118,10 @@
X t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
X t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
X t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
+ .globl t_nmi
X #ifndef __SMP__
X t_nmi: NMI_TRAP /* Level 15 (NMI) */
X #else
- .globl t_nmi
X t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
X #endif
X t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
@@ -842,6 +844,8 @@
X be 1f
X cmp %l1, 'm'
X be 1f
+ cmp %l1, 's'
+ be 1f
X cmp %l1, 'd'
X be 1f
X cmp %l1, 'e'
@@ -853,6 +857,8 @@
X 1: set C_LABEL(cputypval), %l1
X ldub [%l1 + 0x4], %l1
X cmp %l1, 'm' ! Test for sun4d, sun4e ?
+ be sun4m_init
+ cmp %l1, 's' ! Treat sun4s as sun4m
X be sun4m_init
X cmp %l1, 'd' ! Let us see how the beast will die
X be sun4d_init
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.3.5/linux/arch/sparc/kernel/pcic.c Tue Mar 16 21:52:05 1999
+++ linux/arch/sparc/kernel/pcic.c Wed Jun 9 14:44:25 1999
@@ -1,10 +1,13 @@
-/* $Id: pcic.c,v 1.5 1999/03/16 00:15:20 davem Exp $
+/* $Id: pcic.c,v 1.6 1999/06/03 15:02:18 davem Exp $
X * pcic.c: Sparc/PCI controller support
X *
X * Copyright (C) 1998 V. Roganov and G. Raiko
X *
X * Code is derived from Ultra/PCI PSYCHO controller support, see that
X * for author info.
+ *
+ * Support for diverse IIep based platforms by Pete Zaitcev.
+ * CP-1200 by Eric Brower.
X */
X
X #include <linux/config.h>
@@ -16,6 +19,7 @@
X
X #include <asm/ebus.h>
X #include <asm/sbus.h> /* for sanity check... */
+#include <asm/swift.h> /* for cache flushing. */
X
X #include <asm/io.h>
X
@@ -69,9 +73,99 @@
X
X #else
X
+unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
+
+/*
+ * I studied different documents and many live PROMs both from 2.30
+ * family and 3.xx versions. I came to the amazing conclusion: there is
+ * absolutely no way to route interrupts in IIep systems relying on
+ * information which PROM presents. We must hardcode interrupt routing
+ * schematics. And this actually sucks. -- zaitcev 1999/05/12
+ *
+ * To find irq for a device we determine which routing map
+ * is in effect or, in other words, on which machine we are running.
+ * We use PROM name for this although other techniques may be used
+ * in special cases (Gleb reports a PROMless IIep based system).
+ * Once we know the map we take device configuration address and
+ * find PCIC pin number where INT line goes. Then we may either program
+ * preferred irq into the PCIC or supply the preexisting irq to the device.
+ *
+ * XXX Entries for JE-1 are completely bogus. Gleb, Vladimir, please fill them.
+ */
+struct pcic_ca2irq {
+ unsigned char busno; /* PCI bus number */
+ unsigned char devfn; /* Configuration address */
+ unsigned char pin; /* PCIC external interrupt pin */
+ unsigned char irq; /* Preferred IRQ (mappable in PCIC) */
+ unsigned int force; /* Enforce preferred IRQ */
+};
+
+struct pcic_sn2list {
+ char *sysname;
+ struct pcic_ca2irq *intmap;
+ int mapdim;
+};
+
+/*
+ * XXX JE-1 is a little known beast.
+ * One rumor has the map this way: pin 0 - parallel, audio;
+ * pin 1 - Ethernet; pin 2 - su; pin 3 - PS/2 kbd and mouse.
+ * All other comparable systems tie serial and keyboard together,
+ * so we do not code this rumor just yet.
+ */
+static struct pcic_ca2irq pcic_i_je1[] = {
+ { 0, 0x01, 1, 6, 1 }, /* Happy Meal */
+};
+
+/* XXX JS-E entry is incomplete - PCI Slot 2 address (pin 7)? */
+static struct pcic_ca2irq pcic_i_jse[] = {
+ { 0, 0x00, 0, 13, 0 }, /* Ebus - serial and keyboard */
+ { 0, 0x01, 1, 6, 0 }, /* hme */
+ { 0, 0x08, 2, 9, 0 }, /* VGA - we hope not used :) */
+ { 0, 0x18, 6, 8, 0 }, /* PCI INTA# in Slot 1 */
+ { 0, 0x38, 4, 9, 0 }, /* All ISA devices. Read 8259. */
+ { 0, 0x80, 5, 11, 0 }, /* EIDE */
+ /* {0,0x88, 0,0,0} - unknown device... PMU? Probably no interrupt. */
+ { 0, 0xA0, 4, 9, 0 }, /* USB */
+ /*
+ * Some pins belong to non-PCI devices, we hardcode them in drivers.
+ * sun4m timers - irq 10, 14
+ * PC style RTC - pin 7, irq 4 ?
+ * Smart card, Parallel - pin 4 shared with USB, ISA
+ * audio - pin 3, irq 5 ?
+ */
+};
+
+/* SPARCengine-6 was the original release name of CP1200.
+ * The documentation differs between the two versions
+ */
+static struct pcic_ca2irq pcic_i_se6[] = {
+ { 0, 0x08, 0, 2, 0 }, /* SCSI */
+ { 0, 0x01, 1, 6, 0 }, /* HME */
+ { 0, 0x00, 3, 13, 0 }, /* EBus */
+};
+
+/*
+ * Several entries in this list may point to the same routing map
+ * as several PROMs may be installed on the same physical board.
+ */
+#define SN2L_INIT(name, map) \
+ { name, map, sizeof(map)/sizeof(struct pcic_ca2irq) }
+
+static struct pcic_sn2list pcic_known_sysnames[] = {
+ SN2L_INIT("JE-1-name", pcic_i_je1), /* XXX Gleb, put name here, pls */
+ SN2L_INIT("SUNW,JS-E", pcic_i_jse), /* PROLL JavaStation-E */
+ SN2L_INIT("SUNW,SPARCengine-6", pcic_i_se6), /* SPARCengine-6/CP-1200 */
+ { NULL, NULL, 0 }
+};
+
X static struct linux_pcic PCIC;
X static struct linux_pcic *pcic = NULL;
X
+unsigned int pcic_regs;
+volatile int pcic_speculative;
+volatile int pcic_trapped;
+
X static void pci_do_gettimeofday(struct timeval *tv);
X static void pci_do_settimeofday(struct timeval *tv);
X
@@ -149,6 +243,37 @@
X pbm->prom_node = node;
X prom_getstring(node, "name", namebuf, sizeof(namebuf));
X strcpy(pbm->prom_name, namebuf);
+
+ {
+ extern volatile int t_nmi[1];
+ extern int pcic_nmi_trap_patch[1];
+
+ t_nmi[0] = pcic_nmi_trap_patch[0];
+ t_nmi[1] = pcic_nmi_trap_patch[1];
+ t_nmi[2] = pcic_nmi_trap_patch[2];
+ t_nmi[3] = pcic_nmi_trap_patch[3];
+ swift_flush_dcache();
+ pcic_regs = pcic->pcic_regs;
+ }
+
+ prom_getstring(prom_root_node, "name", namebuf, sizeof(namebuf));
+ {
+ struct pcic_sn2list *p;
+
+ for (p = pcic_known_sysnames; p->sysname != NULL; p++) {
+ if (strcmp(namebuf, p->sysname) == 0)
+ break;
+ }
+ pcic->pcic_imap = p->intmap;
+ pcic->pcic_imdim = p->mapdim;
+ }
+ if (pcic->pcic_imap == NULL) {
+ /*
+ * We do not panic here for the sake of embedded systems.
+ */
+ printk("PCIC: System %s is unknown, cannot route interrupts\n",
+ namebuf);
+ }
X }
X
X __initfunc(void pcibios_init(void))
@@ -166,20 +291,15 @@
X pcic->pcic_regs, pcic->pcic_io);
X
X /*
- * FIXME:
X * Switch off IOTLB translation.
- * It'll be great to use IOMMU to handle HME's rings
- * but we couldn't. Thus, we have to flush CPU cache
- * in HME.
X */
X writeb(PCI_DVMA_CONTROL_IOTLB_DISABLE,
X pcic->pcic_regs+PCI_DVMA_CONTROL);
X
X /*
- * FIXME:
X * Increase mapped size for PCI memory space (DMA access).
X * Should be done in that order (size first, address second).
- * Why we couldn't set up 4GB and forget about it ?
+ * Why we couldn't set up 4GB and forget about it? XXX
X */
X writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0);
X writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY,
@@ -204,7 +324,7 @@
X if(err != 0 && err != -1) {
X unsigned long devfn = (regs[0].which_io >> 8) & 0xff;
X if(devfn == pdev->devfn)
- return node; /* Match */
+ return node;
X }
X node = prom_getsibling(node);
X }
@@ -216,9 +336,9 @@
X return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
X }
X
-
-static void pcic_map_pci_device (struct pci_dev *dev) {
- int node, pcinode;
+static void pcic_map_pci_device (struct pci_dev *dev, int node) {
+ struct linux_prom_pci_assigned_addresses addrs[6];
+ int addrlen;
X int i, j;
X
X /* Is any valid address present ? */
@@ -227,74 +347,132 @@
X if (dev->base_address[j]) i++;
X if (!i) return; /* nothing to do */
X
+ if (node == 0 || node == -1) {
+ printk("PCIC: no prom node for device ID (%x,%x)\n",
+ dev->device, dev->vendor);
+ return;
+ }
+
X /*
X * find related address and get it's window length
X */
- pcinode = prom_getchild(prom_root_node);
- pcinode = prom_searchsiblings(pcinode, "pci");
- if (!pcinode)
- panic("PCIC: failed to locate 'pci' node");
-
-
- for (node = prom_getchild(pcinode); node;
- node = prom_getsibling(node)) {
- struct linux_prom_pci_assigned_addresses addrs[6];
- int addrlen = prom_getproperty(node,"assigned-addresses",
+ addrlen = prom_getproperty(node,"assigned-addresses",
X (char*)addrs, sizeof(addrs));
- if (addrlen == -1)
- continue;
+ if (addrlen == -1) {
+ printk("PCIC: no \"assigned-addresses\" for device (%x,%x)\n",
+ dev->device, dev->vendor);
+ return;
+ }
X
- addrlen /= sizeof(struct linux_prom_pci_assigned_addresses);
- for (i = 0; i < addrlen; i++ )
- for (j = 0; j < 6; j++) {
- if (!dev->base_address[j] || !addrs[i].phys_lo)
- continue;
- if (addrs[i].phys_lo == dev->base_address[j]) {
- unsigned long address = dev->base_address[j];
- int length = addrs[i].size_lo;
- char namebuf[128] = { 0, };
- unsigned long mapaddr, addrflags;
-
- prom_getstring(node, "name",
- namebuf, sizeof(namebuf));
-
- /* FIXME:
- * failure in allocation too large space
- */
- if (length > 0x200000) {
+ addrlen /= sizeof(struct linux_prom_pci_assigned_addresses);
+ for (i = 0; i < addrlen; i++ )
+ for (j = 0; j < 6; j++) {
+ if (!dev->base_address[j] || !addrs[i].phys_lo)
+ continue;
+ if (addrs[i].phys_lo == dev->base_address[j]) {
+ unsigned long address = dev->base_address[j];
+ int length = addrs[i].size_lo;
+ char namebuf[128] = { 0, };
+ unsigned long mapaddr, addrflags;
+
+ prom_getstring(node, "name", namebuf, sizeof(namebuf));
+
+ /*
+ * failure in allocation too large space
+ */
+ if (length > 0x200000) {
X length = 0x200000;
X prom_printf("PCIC: map window for device '%s' "
X "reduced to 2MB !\n", namebuf);
- }
+ }
X
- /*
- * Be careful with MEM/IO address flags
- */
- if ((address & PCI_BASE_ADDRESS_SPACE) ==
+ /*
+ * Be careful with MEM/IO address flags
+ */
+ if ((address & PCI_BASE_ADDRESS_SPACE) ==
X PCI_BASE_ADDRESS_SPACE_IO) {
X mapaddr = address & PCI_BASE_ADDRESS_IO_MASK;
- } else {
+ } else {
X mapaddr = address & PCI_BASE_ADDRESS_MEM_MASK;
- }
- addrflags = address ^ mapaddr;
+ }
+ addrflags = address ^ mapaddr;
X
- dev->base_address[j] =
+ dev->base_address[j] =
X (unsigned long)sparc_alloc_io(address, 0,
X length,
X namebuf, 0, 0);
- if ( dev->base_address[j] == 0 )
+ if ( dev->base_address[j] == 0 )
X panic("PCIC: failed make mapping for "
X "pci device '%s' with address %lx\n",
X namebuf, address);
X
- dev->base_address[j] ^= addrflags;
- return;
- }
+ dev->base_address[j] ^= addrflags;
+ return;
X }
+ }
+
+ printk("PCIC: unable to match addresses for device (%x,%x)\n",
+ dev->device, dev->vendor);
+}
+
+static void pcic_fill_irq(struct pci_dev *dev, int node) {
+ struct pcic_ca2irq *p;
+ int i, ivec;
+ char namebuf[64]; /* P3 remove */
+
+ if (node == -1) {
+ strcpy(namebuf, "???");
+ } else {
+ prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */
X }
X
- panic("PCIC: unable to locate prom node for pci device (%x,%x) \n",
- dev->device, dev->vendor);
+ if ((p = pcic->pcic_imap) == 0) {
+ dev->irq = 0;
+ return;
+ }
+ for (i = 0; i < pcic->pcic_imdim; i++) {
+ if (p->busno == dev->bus->number && p->devfn == dev->devfn)
+ break;
+ p++;
+ }
+ if (i >= pcic->pcic_imdim) {
+ printk("PCIC: device %s devfn %02x:%02x not found in %d\n",
+ namebuf, dev->bus->number, dev->devfn, pcic->pcic_imdim);
+ dev->irq = 0;
+ return;
+ }
+
+ i = p->pin;
+ if (i >= 0 && i < 4) {
+ ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
+ dev->irq = ivec >> (i << 2) & 0xF;
+ } else if (i >= 4 && i < 8) {
+ ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
+ dev->irq = ivec >> ((i-4) << 2) & 0xF;
+ } else { /* Corrupted map */
+ printk("PCIC: BAD PIN %d\n", i); for (;;) {}
+ }
+/* P3 remove later */ printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq);
+
+ /*
+ * dev->irq=0 means PROM did not bothered to program the upper
+ * half of PCIC. This happens on JS-E with PROM 3.11, for instance.
+ */
+ if (dev->irq == 0 || p->force) {
+ if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */
+ printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
+ }
+ printk("PCIC: setting irq %x for device (%x,%x)\n",
+ p->irq, dev->device, dev->vendor);
+ dev->irq = p->irq;
+
+ ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
+ ivec &= ~(0xF << ((p->pin - 4) << 2));
+ ivec |= p->irq << ((p->pin - 4) << 2);
+ writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_HI);
+ }
+
+ return;
X }
X
X /*
@@ -317,9 +495,10 @@
X writeb((pcic->pcic_io_phys>>24) & PCI_SIBAR_ADDRESS_MASK,
X pcic->pcic_regs+PCI_SIBAR);
X writeb(PCI_ISIZE_16M, pcic->pcic_regs+PCI_ISIZE);
+
X }
X if(paddr < pcic->pcic_mapped_io ||
- paddr > pcic->pcic_mapped_io + PCI_SPACE_SIZE)
+ paddr >= pcic->pcic_mapped_io + 0x10000)
X return 0;
X offset = paddr - pcic->pcic_mapped_io;
X *addr = pcic->pcic_io_phys + offset;
@@ -334,6 +513,9 @@
X struct pci_dev *dev;
X int i, has_io, has_mem;
X unsigned short cmd;
+ struct linux_pbm_info* pbm = &pcic->pbm;
+ int node;
+ struct pcidev_cookie *pcp;
X
X if(pcic == NULL) {
X prom_printf("PCI: Error, PCIC not found.\n");
@@ -359,47 +541,61 @@
X }
X pci_read_config_word(dev, PCI_COMMAND, &cmd);
X if (has_io && !(cmd & PCI_COMMAND_IO)) {
- printk("PCI: Enabling I/O for device %02x:%02x\n",
+ printk("PCIC: Enabling I/O for device %02x:%02x\n",
X dev->bus->number, dev->devfn);
X cmd |= PCI_COMMAND_IO;
X pci_write_config_word(dev, PCI_COMMAND, cmd);
X }
X if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
- printk("PCI: Enabling memory for device %02x:%02x\n",
+ printk("PCIC: Enabling memory for device %02x:%02x\n",
X dev->bus->number, dev->devfn);
X cmd |= PCI_COMMAND_MEMORY;
X pci_write_config_word(dev, PCI_COMMAND, cmd);
X }
X
+ node = pdev_to_pnode(pbm, dev);
+ if(node == 0)
+ node = -1;
+
X /* cookies */
- {
- struct pcidev_cookie *pcp;
- struct linux_pbm_info* pbm = &pcic->pbm;
- int node = pdev_to_pnode(pbm, dev);
-
- if(node == 0)
- node = -1;
- pcp = pci_devcookie_alloc();
- pcp->pbm = pbm;
- pcp->prom_node = node;
- dev->sysdata = pcp;
- }
+ pcp = pci_devcookie_alloc();
+ pcp->pbm = pbm;
+ pcp->prom_node = node;
+ dev->sysdata = pcp;
X
X /* memory mapping */
- if (!(dev->vendor == PCI_VENDOR_ID_SUN &&
- dev->device == PCI_DEVICE_ID_SUN_EBUS)) {
- pcic_map_pci_device(dev);
- }
+ if ((dev->class>>16) != PCI_BASE_CLASS_BRIDGE)
+ pcic_map_pci_device(dev, node);
X
- /* irq */
-#define SETIRQ(vend,devid,irqn) \
- if (dev->vendor==vend && dev->device==devid) dev->irq = irqn;
-
- SETIRQ(PCI_VENDOR_ID_SUN,PCI_DEVICE_ID_SUN_HAPPYMEAL,3);
+ pcic_fill_irq(dev, node);
X }
+
X ebus_init();
X }
X
+/*
+ * pcic_pin_to_irq() is exported to ebus.c.
+ */
+unsigned int
+pcic_pin_to_irq(unsigned int pin, char *name)
+{
+ unsigned int irq;
+ unsigned int ivec;
+
+ if (pin < 4) {
+ ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
+ irq = ivec >> (pin << 2) & 0xF;
+ } else if (pin < 8) {
+ ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
+ irq = ivec >> ((pin-4) << 2) & 0xF;
+ } else { /* Corrupted map */
+ printk("PCIC: BAD PIN %d FOR %s\n", pin, name);
+ for (;;) {} /* XXX Cannot panic properly in case of PROLL */
+ }
+/* P3 remove later */ printk("PCIC: dev %s pin %d ivec 0x%x irq %x\n", name, pin, ivec, irq);
+ return irq;
+}
+
X /* Makes compiler happy */
X static volatile int pcic_timer_dummy;
X
@@ -539,26 +735,38 @@
X unsigned char where, unsigned int *value)
X {
X unsigned long flags;
- if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
- if (bus != 0 ||
- (device_fn != 0 && device_fn != 1 && device_fn != 0x80)) {
- *value = 0xffffffff;
- return PCIBIOS_SUCCESSFUL;
- }
X
- /* FIXME: IGA haven't got high config memory addresses !!! */
- if (device_fn == 0x80 && where > PCI_INTERRUPT_LINE) {
- *value = 0xffffffff;
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
X
X save_and_cli(flags);
+#if 0
+ pcic_speculative = 1;
+ pcic_trapped = 0;
+#endif
X writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr);
+#if 0
+ nop();
+ if (pcic_trapped) {
+ restore_flags(flags);
+ *value = ~0;
+ return PCIBIOS_SUCCESSFUL;
+ }
+#endif
+ pcic_speculative = 2;
+ pcic_trapped = 0;
X *value = readl(pcic->pcic_config_space_data + (where&4));
+ nop();
+ if (pcic_trapped) {
+ pcic_speculative = 0;
+ restore_flags(flags);
+ *value = ~0;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pcic_speculative = 0;
X restore_flags(flags);
X return PCIBIOS_SUCCESSFUL;
X }
-
+
X int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
X unsigned char where, unsigned char value)
X {
@@ -586,8 +794,8 @@
X unsigned char where, unsigned int value)
X {
X unsigned long flags;
- if ((where&3) || bus != 0 || (devfn != 0 && devfn != 1 && devfn != 0x80))
- return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
X
X save_and_cli(flags);
X writel(CONFIG_CMD(bus,devfn,where),pcic->pcic_config_space_addr);
@@ -599,6 +807,29 @@
X __initfunc(char *pcibios_setup(char *str))
X {
X return str;
+}
+
+/*
+ * NMI
+ */
+void pcic_nmi(unsigned int pend, struct pt_regs *regs)
+{
+
+ pend = flip_dword(pend);
+
+ if (!pcic_speculative || (pend & PCI_SYS_INT_PENDING_PIO) == 0) {
+ /*
+ * XXX On CP-1200 PCI #SERR may happen, we do not know
+ * what to do about it yet.
+ */
+ printk("Aiee, NMI pend 0x%x pc 0x%x spec %d, hanging\n",
+ pend, (int)regs->pc, pcic_speculative);
+ for (;;) { }
+ }
+ pcic_speculative = 0;
+ pcic_trapped = 1;
+ regs->pc = regs->npc;
+ regs->npc += 4;
X }
X
X /*
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- v2.3.5/linux/arch/sparc/kernel/ptrace.c Mon May 31 22:28:04 1999
+++ linux/arch/sparc/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -134,26 +134,6 @@


X flush_tlb_page(vma, addr);
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,

- unsigned long addr)


-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm,addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.

diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.3.5/linux/arch/sparc/kernel/setup.c Mon May 31 22:28:04 1999
+++ linux/arch/sparc/kernel/setup.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.106 1999/05/28 16:03:18 anton Exp $
+/* $Id: setup.c,v 1.107 1999/06/03 15:02:20 davem Exp $
X * linux/arch/sparc/kernel/setup.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -313,6 +313,7 @@
X if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
X if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; }
X if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; }
+ if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; } /* CP-1200 with PROM 2.30 -E */
X if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; }
X if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; }
X if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; }
diff -u --recursive --new-file v2.3.5/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.3.5/linux/arch/sparc/kernel/sys_sunos.c Mon May 31 22:28:04 1999
+++ linux/arch/sparc/kernel/sys_sunos.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.97 1999/05/24 19:40:39 davem Exp $
+/* $Id: sys_sunos.c,v 1.98 1999/06/09 08:23:39 davem Exp $
X * sys_sunos.c: SunOS specific syscall compatibility support.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -150,7 +150,6 @@
X unsigned long newbrk, oldbrk;
X
X down(&current->mm->mmap_sem);
- lock_kernel();
X if(ARCH_SUN4C_SUN4) {
X if(brk >= 0x20000000 && brk < 0xe0000000) {
X goto out;
@@ -210,12 +209,9 @@
X * Ok, we have probably got enough memory - let it rip.
X */
X current->mm->brk = brk;


- do_mmap(NULL, oldbrk, newbrk-oldbrk,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ do_brk(oldbrk, newbrk-oldbrk)
X retval = 0;
X out:
- unlock_kernel();
X up(&current->mm->mmap_sem);
X return retval;
X }
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.3.5/linux/arch/sparc64/Makefile Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc64/Makefile Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.35 1999/01/02 16:45:50 davem Exp $
+# $Id: Makefile,v 1.37 1999/06/04 13:29:10 jj Exp $
X # sparc64/Makefile
X #
X # Makefile for the architecture dependent flags and dependencies on the
@@ -15,7 +15,7 @@
X CC := sparc64-linux-gcc -D__KERNEL__ -I$(TOPDIR)/include
X
X CC_HAS_ARGS := $(shell if echo "$(CC)" | grep '\(__KERNEL__\| \)' > /dev/null; then echo y; else echo n; fi)
-IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi)
+IS_EGCS := $(shell if $(CC) -c -m64 -mcmodel=medlow -o _tmp.o arch/sparc64/math-emu/fnegq.c >/dev/null 2>&1; then echo y; else echo n; fi; rm -f _tmp.o)
X NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
X
X ifneq ($(CC_HAS_ARGS),y)
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.5/linux/arch/sparc64/defconfig Mon May 31 22:28:04 1999
+++ linux/arch/sparc64/defconfig Wed Jun 9 14:44:25 1999
@@ -69,6 +69,8 @@
X # CONFIG_SUN_BPP is not set
X # CONFIG_SUN_VIDEOPIX is not set
X CONFIG_SUN_AURORA=m
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_RTC is not set
X
X #
X # Linux/SPARC audio subsystem (EXPERIMENTAL)
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c
--- v2.3.5/linux/arch/sparc64/kernel/binfmt_aout32.c Mon Mar 22 10:06:36 1999
+++ linux/arch/sparc64/kernel/binfmt_aout32.c Wed Jun 9 14:44:25 1999
@@ -48,9 +48,7 @@


X end = PAGE_ALIGN(end);
X if (end <= start)
X return;
- do_mmap(NULL, start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, 0);
+ do_brk(start, end - start);
X }
X

X /*
@@ -284,24 +282,18 @@
X current->flags &= ~PF_FORKNOEXEC;
X if (N_MAGIC(ex) == NMAGIC) {
X /* Fuck me plenty... */
- error = do_mmap(NULL, N_TXTADDR(ex), ex.a_text,


- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ error = do_brk(N_TXTADDR(ex), ex.a_text);
X read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
X ex.a_text, 0);
- error = do_mmap(NULL, N_DATADDR(ex), ex.a_data,


- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ error = do_brk(N_DATADDR(ex), ex.a_data);
X read_exec(bprm->dentry, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
X ex.a_data, 0);
X goto beyond_if;
X }
X
X if (N_MAGIC(ex) == OMAGIC) {
- do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
- ex.a_text+ex.a_data + PAGE_SIZE - 1,


- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ do_brk(N_TXTADDR(ex) & PAGE_MASK,
+ ex.a_text+ex.a_data + PAGE_SIZE - 1);
X read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
X ex.a_text+ex.a_data, 0);
X } else {
@@ -316,9 +308,7 @@
X
X if (!file->f_op || !file->f_op->mmap) {
X sys_close(fd);
- do_mmap(NULL, 0, ex.a_text+ex.a_data,


- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ do_brk(0, ex.a_text+ex.a_data);
X read_exec(bprm->dentry, fd_offset,
X (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
X goto beyond_if;
@@ -359,11 +349,16 @@
X
X set_brk(current->mm->start_brk, current->mm->brk);
X
- p = setup_arg_pages(p, bprm);
+ retval = setup_arg_pages(bprm);
+ if (retval < 0) {
+ /* Someone check-me: is this error path enough? */
+ send_sig(SIGKILL, current, 0);
+ return retval;
+ }
X
- p = (unsigned long) create_aout32_tables((char *)p, bprm);
- current->mm->start_stack = p;
- start_thread32(regs, ex.a_entry, p);
+ current->mm->start_stack =
+ (unsigned long) create_aout32_tables((char *)bprm->p, bprm);
+ start_thread32(regs, ex.a_entry, current->mm->start_stack);
X if (current->flags & PF_PTRACED)
X send_sig(SIGTRAP, current, 0);
X return 0;
@@ -442,9 +437,7 @@
X len = PAGE_ALIGN(ex.a_text + ex.a_data);
X bss = ex.a_text + ex.a_data + ex.a_bss;
X if (bss > len) {
- error = do_mmap(NULL, start_addr + len, bss - len,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_FIXED, 0);
+ error = do_brk(start_addr + len, bss - len);
X retval = error;
X if (error != start_addr + len)
X goto out_putf;
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.5/linux/arch/sparc64/kernel/ioctl32.c Tue May 11 08:24:31 1999
+++ linux/arch/sparc64/kernel/ioctl32.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.62 1999/05/01 09:17:44 davem Exp $
+/* $Id: ioctl32.c,v 1.63 1999/06/09 04:56:14 davem Exp $
X * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
X *
X * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -37,6 +37,7 @@
X #include <linux/fb.h>
X #include <linux/ext2_fs.h>
X #include <linux/videodev.h>
+#include <linux/netdevice.h>
X
X #include <scsi/scsi.h>
X /* Ugly hack. */
@@ -417,6 +418,23 @@
X __kernel_caddr_t32 ifcbuf;
X };
X
+static int dev_ifname32(unsigned int fd, unsigned long arg)
+{
+ struct device *dev;
+ struct ifreq32 ifr32;
+ int err;
+
+ if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+ return -EFAULT;
+
+ dev = dev_get_by_index(ifr32.ifr_ifindex);
+ if (!dev)
+ return -ENODEV;
+
+ err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
+ return (err ? -EFAULT : 0);
+}
+
X static inline int dev_ifconf(unsigned int fd, unsigned long arg)
X {
X struct ifconf32 ifc32;
@@ -1687,6 +1705,10 @@
X goto out;
X }
X switch (cmd) {
+ case SIOCGIFNAME:
+ error = dev_ifname32(fd, arg);
+ goto out;
+
X case SIOCGIFCONF:
X error = dev_ifconf(fd, arg);
X goto out;
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- v2.3.5/linux/arch/sparc64/kernel/ptrace.c Mon May 31 22:28:04 1999
+++ linux/arch/sparc64/kernel/ptrace.c Mon Jun 7 11:15:33 1999
@@ -204,26 +204,6 @@


X flush_tlb_page(vma, addr);
X }
X
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,

- unsigned long addr)


-{
- struct vm_area_struct * vma;
-
- addr &= PAGE_MASK;
- vma = find_vma(tsk->mm,addr);
- if (!vma)
- return NULL;
- if (vma->vm_start <= addr)
- return vma;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return NULL;
- if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
- return NULL;
- vma->vm_offset -= vma->vm_start - addr;
- vma->vm_start = addr;
- return vma;
-}
-
X /*
X * This routine checks the page boundaries, and that the offset is
X * within the task area. It then calls get_long() to read a long.

diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c
--- v2.3.5/linux/arch/sparc64/kernel/signal.c Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc64/kernel/signal.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.38 1998/10/16 03:19:04 davem Exp $
+/* $Id: signal.c,v 1.40 1999/06/02 19:19:52 jj Exp $
X * arch/sparc64/kernel/signal.c
X *
X * Copyright (C) 1991, 1992 Linus Torvalds
@@ -491,7 +491,7 @@
X /* Checks if the fp is valid */
X static int invalid_frame_pointer(void *fp, int fplen)
X {
- if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x80000000000ULL - fplen)
+ if (((unsigned long) fp) & 7)
X return 1;
X return 0;
X }
@@ -554,8 +554,10 @@
X goto sigill;
X
X if (current->tss.w_saved != 0) {
+#ifdef DEBUG_SIGNALS
X printk ("%s[%d]: Invalid user stack frame for "
X "signal delivery.\n", current->comm, current->pid);
+#endif
X goto sigill;
X }
X
@@ -590,35 +592,7 @@
X regs->tnpc = (regs->tpc + 4);
X
X /* 4. return to kernel instructions */
- if (ka->ka_restorer)
- regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
- else {
- /* Flush instruction space. */
- unsigned long address = ((unsigned long)&(sf->insns[0]));
- pgd_t *pgdp = pgd_offset(current->mm, address);
- pmd_t *pmdp = pmd_offset(pgdp, address);
- pte_t *ptep = pte_offset(pmdp, address);
-
- regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
-
- /* mov __NR_sigreturn, %g1 */
- err |= __put_user(0x821020d8, &sf->insns[0]);
-
- /* t 0x6d */
- err |= __put_user(0x91d0206d, &sf->insns[1]);
- if (err)
- goto sigsegv;
-
- if(pte_present(*ptep)) {
- unsigned long page = pte_page(*ptep);
-
- __asm__ __volatile__("
- membar #StoreStore
- flush %0 + %1"
- : : "r" (page), "r" (address & (PAGE_SIZE - 1))
- : "memory");
- }
- }
+ regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
X return;
X
X sigill:
@@ -650,8 +624,10 @@
X goto sigill;
X
X if (current->tss.w_saved != 0) {
+#ifdef DEBUG_SIGNALS
X printk ("%s[%d]: Invalid user stack frame for "
X "signal delivery.\n", current->comm, current->pid);
+#endif
X goto sigill;
X }
X
@@ -690,35 +666,7 @@
X regs->tnpc = (regs->tpc + 4);
X
X /* 4. return to kernel instructions */
- if (ka->ka_restorer)
- regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
- else {
- /* Flush instruction space. */
- unsigned long address = ((unsigned long)&(sf->insns[0]));
- pgd_t *pgdp = pgd_offset(current->mm, address);
- pmd_t *pmdp = pmd_offset(pgdp, address);
- pte_t *ptep = pte_offset(pmdp, address);
-
- regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
-
- /* mov __NR_rt_sigreturn, %g1 */
- err |= __put_user(0x82102065, &sf->insns[0]);
-
- /* t 0x6d */
- err |= __put_user(0x91d0206d, &sf->insns[1]);
- if (err)
- goto sigsegv;
-
- if(pte_present(*ptep)) {
- unsigned long page = pte_page(*ptep);
-
- __asm__ __volatile__("
- membar #StoreStore
- flush %0 + %1"
- : : "r" (page), "r" (address & (PAGE_SIZE - 1))
- : "memory");
- }
- }
+ regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
X return;
X
X sigill:
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.3.5/linux/arch/sparc64/kernel/sys_sparc.c Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/kernel/sys_sparc.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.26 1999/01/07 19:07:01 jj Exp $
+/* $Id: sys_sparc.c,v 1.27 1999/06/02 12:06:34 jj Exp $
X * linux/arch/sparc64/kernel/sys_sparc.c
X *
X * This file contains various random system calls that
@@ -325,39 +325,6 @@
X return -EINVAL;
X regs->tstate = (regs->tstate & ~TSTATE_MM) | (model << 14);
X return 0;
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- new_ka.ka_restorer = NULL;
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
-
- return ret;
X }
X
X asmlinkage int
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.5/linux/arch/sparc64/kernel/sys_sparc32.c Mon May 17 09:55:21 1999
+++ linux/arch/sparc64/kernel/sys_sparc32.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.108 1999/05/16 10:50:32 davem Exp $
+/* $Id: sys_sparc32.c,v 1.109 1999/06/03 07:11:31 davem Exp $
X * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
X *
X * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -2776,42 +2776,46 @@
X * memory to free pages in kernel mem. These are in a format ready
X * to be put directly into the top of new user memory.
X */
-static unsigned long
-copy_strings32(int argc,u32 * argv,unsigned long *page,
- unsigned long p)
+static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
X {
- u32 str;
-
- if (!p) return 0; /* bullet-proofing */
X while (argc-- > 0) {
+ u32 str;
X int len;
X unsigned long pos;
X
- get_user(str, argv+argc);
- if (!str) panic("VFS: argc is wrong");
- len = strlen_user((char *)A(str)); /* includes the '\0' */
- if (p < len) /* this shouldn't happen - 128kB */
- return 0;
- p -= len; pos = p;
+ if (get_user(str, argv + argc) ||
+ !str ||
+ !(len = strlen_user((char *)A(str))))
+ return -EFAULT;
+ if (bprm->p < len)
+ return -E2BIG;
+
+ bprm->p -= len;
+
+ pos = bprm->p;
X while (len) {
X char *pag;
X int offset, bytes_to_copy;
X
X offset = pos % PAGE_SIZE;
- if (!(pag = (char *) page[pos/PAGE_SIZE]) &&
- !(pag = (char *) page[pos/PAGE_SIZE] =
+ if (!(pag = (char *) bprm->page[pos/PAGE_SIZE]) &&
+ !(pag = (char *) bprm->page[pos/PAGE_SIZE] =
X (unsigned long *) get_free_page(GFP_USER)))
- return 0;
+ return -ENOMEM;
+
X bytes_to_copy = PAGE_SIZE - offset;
X if (bytes_to_copy > len)
X bytes_to_copy = len;
- copy_from_user(pag + offset, (char *)A(str), bytes_to_copy);
+
+ if (copy_from_user(pag + offset, (char *)A(str), bytes_to_copy))
+ return -EFAULT;
+
X pos += bytes_to_copy;
X str += bytes_to_copy;
X len -= bytes_to_copy;
X }
X }
- return p;
+ return 0;
X }
X
X /*
@@ -2850,29 +2854,36 @@
X }
X
X retval = prepare_binprm(&bprm);
+ if (retval < 0)
+ goto out;
X
- if(retval>=0) {
- bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
- bprm.exec = bprm.p;
- bprm.p = copy_strings32(bprm.envc,envp,bprm.page,bprm.p);
- bprm.p = copy_strings32(bprm.argc,argv,bprm.page,bprm.p);
- if (!bprm.p)
- retval = -E2BIG;
- }
+ retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+ if (retval < 0)
+ goto out;
+
+ bprm.exec = bprm.p;
+ retval = copy_strings32(bprm.envc, envp, &bprm);
+ if (retval < 0)
+ goto out;
X
- if(retval>=0)
- retval = search_binary_handler(&bprm,regs);
- if(retval>=0)
+ retval = copy_strings32(bprm.argc, argv, &bprm);
+ if (retval < 0)
+ goto out;
+
+ retval = search_binary_handler(&bprm, regs);
+ if (retval >= 0)
X /* execve success */
X return retval;
X
+out:
X /* Something went wrong, return the inode and free the argument pages*/
- if(bprm.dentry)
+ if (bprm.dentry)
X dput(bprm.dentry);
X
X for (i=0 ; i<MAX_ARG_PAGES ; i++)
X free_page(bprm.page[i]);
- return(retval);
+
+ return retval;
X }
X
X /*
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.5/linux/arch/sparc64/kernel/sys_sunos32.c Mon May 31 22:28:04 1999
+++ linux/arch/sparc64/kernel/sys_sunos32.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.25 1999/05/24 19:40:44 davem Exp $
+/* $Id: sys_sunos32.c,v 1.26 1999/06/09 08:23:54 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)
@@ -134,7 +134,6 @@
X unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
X
X down(&current->mm->mmap_sem);
- lock_kernel();
X if (brk < current->mm->end_code)
X goto out;
X newbrk = PAGE_ALIGN(brk);
@@ -175,12 +174,9 @@
X goto out;
X /* Ok, we have probably got enough memory - let it rip. */
X current->mm->brk = brk;


- do_mmap(NULL, oldbrk, newbrk-oldbrk,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ do_brk(oldbrk, newbrk-oldbrk);
X retval = 0;
X out:
- unlock_kernel();
X up(&current->mm->mmap_sem);
X return retval;
X }
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.3.5/linux/arch/sparc64/kernel/systbls.S Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/kernel/systbls.S Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.53 1999/04/07 17:14:11 davem Exp $
+/* $Id: systbls.S,v 1.54 1999/06/02 12:06:31 jj Exp $
X * systbls.S: System call entry point tables for OS compatibility.
X * The native Linux system call table lives here also.
X *
@@ -115,7 +115,7 @@
X /*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
X .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
X /*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
- .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_sigaction, sys_sgetmask
+ .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
X /*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall
X .word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
X /*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.3.5/linux/arch/sparc64/kernel/traps.c Mon May 31 22:28:04 1999
+++ linux/arch/sparc64/kernel/traps.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.59 1999/05/18 16:57:10 jj Exp $
+/* $Id: traps.c,v 1.60 1999/06/02 19:19:55 jj Exp $
X * arch/sparc64/kernel/traps.c
X *
X * Copyright (C) 1995,1997 David S. Miller (da...@caip.rutgers.edu)
@@ -282,11 +282,16 @@
X unsigned long sfsr, unsigned long sfar)
X {
X lock_kernel();
+ if (regs->tstate & TSTATE_PRIV) {
X #if 1
- printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
- sfsr, sfar);
+ printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
+ sfsr, sfar);
X #endif
- die_if_kernel("Iax", regs);
+ die_if_kernel("Iax", regs);
+ }
+ current->tss.sig_desc = SUBSIG_ILLINST;
+ current->tss.sig_address = regs->tpc;
+ force_sig(SIGILL, current);
X unlock_kernel();
X }
X
diff -u --recursive --new-file v2.3.5/linux/arch/sparc64/math-emu/sfp-util.h linux/arch/sparc64/math-emu/sfp-util.h
--- v2.3.5/linux/arch/sparc64/math-emu/sfp-util.h Mon May 31 22:28:05 1999
+++ linux/arch/sparc64/math-emu/sfp-util.h Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: sfp-util.h,v 1.1 1999/05/28 13:43:07 jj Exp $
+/* $Id: sfp-util.h,v 1.2 1999/06/07 18:24:15 jj Exp $
X * arch/sparc64/math-emu/sfp-util.h
X *
X * Copyright (C) 1999 Jakub Jelinek (j...@ultra.linux.cz)
@@ -55,7 +55,7 @@
X srlx %7,32,%5
X mulx %3,%5,%3
X mulx %2,%5,%5
- sethi 0x80000000,%2
+ sethi %%hi(0x80000000),%2
X addcc %4,%3,%4
X srlx %4,32,%4
X add %2,%2,%2
diff -u --recursive --new-file v2.3.5/linux/drivers/Makefile linux/drivers/Makefile
--- v2.3.5/linux/drivers/Makefile Mon May 10 10:18:34 1999
+++ linux/drivers/Makefile Wed Jun 2 14:40:22 1999
@@ -53,6 +53,15 @@
X endif
X endif
X
+ifeq ($(CONFIG_I2O),y)
+SUB_DIRS += i2o
+MOD_SUB_DIRS += i2o
+else
+ ifeq ($(CONFIG_I2O),m)
+ MOD_SUB_DIRS += i2o
+ endif
+endif
+
X # If CONFIG_SCSI is set, the core of SCSI support will be added to the kernel,
X # but some of the low-level things may also be modules.
X ifeq ($(CONFIG_SCSI),y)
diff -u --recursive --new-file v2.3.5/linux/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c
--- v2.3.5/linux/drivers/block/cy82c693.c Mon May 31 22:28:05 1999
+++ linux/drivers/block/cy82c693.c Wed Jun 2 22:21:51 1999
@@ -423,7 +423,8 @@
X __initfunc(void ide_init_cy82c693(ide_hwif_t *hwif))
X {
X hwif->chipset = ide_cy82c693;
- hwif->dmaproc = &cy82c693_dmaproc;
+ if (hwif->dma_base)
+ hwif->dmaproc = &cy82c693_dmaproc;
X hwif->tuneproc = &cy82c693_tune_drive;
X
X init_cy82c693_chip(hwif->pci_dev);
diff -u --recursive --new-file v2.3.5/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.5/linux/drivers/block/floppy.c Mon May 17 09:55:21 1999
+++ linux/drivers/block/floppy.c Wed Jun 9 16:42:58 1999
@@ -1927,8 +1927,6 @@
X
X static void floppy_ready(void)
X {
- unsigned long flags;
-
X CHECK_RESET;
X if (start_motor(floppy_ready)) return;
X if (fdc_dtr()) return;
@@ -1948,7 +1946,7 @@
X if ((raw_cmd->flags & FD_RAW_READ) ||
X (raw_cmd->flags & FD_RAW_WRITE))
X {
- flags=claim_dma_lock();
+ unsigned long flags = claim_dma_lock();
X fd_chose_dma_mode(raw_cmd->kernel_data,
X raw_cmd->length);
X release_dma_lock(flags);
diff -u --recursive --new-file v2.3.5/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- v2.3.5/linux/drivers/block/ide-pmac.c Fri May 14 18:55:14 1999


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part03

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


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

+++ linux/drivers/block/ide-pmac.c Mon Jun 7 12:12:22 1999
@@ -65,7 +65,6 @@
X ide_ioreg_t ctrl_port,
X int *irq)
X {
- ide_ioreg_t reg = ide_ioreg_t data_port;
X int i, r;
X
X if (data_port == 0)
@@ -76,20 +75,15 @@
X r = check_media_bay_by_base(data_port, MB_CD);
X if (r == -EINVAL)
X return;
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg * 0x10;
- reg += 1;
- }
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
- hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x160;
- }
+
+ for ( i = 0; i < 8 ; ++i )
+ hw->io_ports[i] = data_port + i * 0x10;
+ hw->io_ports[8] = data_port + 0x160;
+
X if (irq != NULL) {
X *irq = 0;
X for (i = 0; i < MAX_HWIFS; ++i) {
- if (base == pmac_ide_regbase[i]) {
+ if (data_port == pmac_ide_regbase[i]) {
X *irq = pmac_ide_irq[i];
X break;
X }
@@ -156,7 +150,7 @@
X np->full_name);
X continue;
X }
-
+
X base = (unsigned long) ioremap(np->addrs[0].address, 0x200);
X
X /* XXX This is bogus. Should be fixed in the registry by checking
diff -u --recursive --new-file v2.3.5/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.5/linux/drivers/block/ll_rw_blk.c Fri May 14 18:55:14 1999
+++ linux/drivers/block/ll_rw_blk.c Wed Jun 2 22:21:51 1999
@@ -471,6 +471,8 @@
X case IDE3_MAJOR:
X case IDE4_MAJOR:
X case IDE5_MAJOR:
+ case IDE6_MAJOR:
+ case IDE7_MAJOR:
X case ACSI_MAJOR:
X case MFM_ACORN_MAJOR:
X /*
@@ -497,6 +499,7 @@
X case SCSI_DISK6_MAJOR:
X case SCSI_DISK7_MAJOR:
X case SCSI_CDROM_MAJOR:
+ case I2O_MAJOR:
X
X do {
X if (req->sem)
diff -u --recursive --new-file v2.3.5/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c
--- v2.3.5/linux/drivers/block/ns87415.c Mon May 31 22:28:05 1999
+++ linux/drivers/block/ns87415.c Wed Jun 2 22:21:51 1999
@@ -166,13 +166,15 @@
X #endif
X }
X
- outb(0x60, hwif->dma_base + 2);
+ if (hwif->dma_base)
+ outb(0x60, hwif->dma_base + 2);
X
X if (!using_inta)
X hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */
X else if (!hwif->irq && hwif->mate && hwif->mate->irq)
X hwif->irq = hwif->mate->irq; /* share IRQ with mate */
X
- hwif->dmaproc = &ns87415_dmaproc;
+ if (hwif->dma_base)
+ hwif->dmaproc = &ns87415_dmaproc;
X hwif->selectproc = &ns87415_selectproc;
X }
diff -u --recursive --new-file v2.3.5/linux/drivers/block/piix.c linux/drivers/block/piix.c
--- v2.3.5/linux/drivers/block/piix.c Fri May 14 18:55:14 1999
+++ linux/drivers/block/piix.c Wed Jun 2 22:21:51 1999


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

- * linux/drivers/block/piix.c Version 0.22 March 29, 1999
+ * linux/drivers/block/piix.c Version 0.23 May 29, 1999
X *
X * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
X * Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer
@@ -13,10 +13,10 @@
X * 41
X * 43
X *
- * | PIO 0 | c0 | 80 | 0 |
- * | PIO 2 | SW2 | d0 | 90 | 4 |
- * | PIO 3 | MW1 | e1 | a1 | 9 |
- * | PIO 4 | MW2 | e3 | a3 | b |
+ * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0);
+ * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2);
+ * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3);
+ * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4);
X *
X * sitre = word40 & 0x4000; primary
X * sitre = word42 & 0x4000; secondary
@@ -58,10 +58,40 @@
X
X #include "ide_modes.h"
X
-#define PIIX_DMA_PROC 0
-#define PIIX_DEBUG_SET_XFER 0
X #define PIIX_DEBUG_DRIVE_INFO 0
X
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ *
+ */
+static byte piix_dma_2_pio (byte xfer_rate) {
+ switch(xfer_rate) {
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ case XFER_MW_DMA_2:
+ case XFER_PIO_4:
+ return 4;
+ case XFER_MW_DMA_1:
+ case XFER_PIO_3:
+ return 3;
+ case XFER_SW_DMA_2:
+ case XFER_PIO_2:
+ return 2;
+ case XFER_MW_DMA_0:
+ case XFER_SW_DMA_1:
+ case XFER_SW_DMA_0:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ case XFER_PIO_SLOW:
+ default:
+ return 0;
+ }
+}
+
X /*
X * Based on settings done by AMI BIOS
X * (might be usefull if drive is not registered in CMOS for any reason).
@@ -70,19 +100,22 @@


X {
X unsigned long flags;

X u16 master_data;
- byte slave_data, speed;
- int err;
- int is_slave = (&HWIF(drive)->drives[1] == drive);
- int master_port = HWIF(drive)->index ? 0x42 : 0x40;
- int slave_port = 0x44;
- /* ISP RTC */
- byte timings[][2] = { { 0, 0 },
- { 0, 0 },
- { 1, 0 },
- { 2, 1 },
- { 2, 3 }, };
-
+ byte slave_data;
+ int is_slave = (&HWIF(drive)->drives[1] == drive);
+ int master_port = HWIF(drive)->index ? 0x42 : 0x40;
+ int slave_port = 0x44;
+ /* ISP RTC */
+ byte timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+#if 1
+ pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+#else
X pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+#endif
X pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
X if (is_slave) {
X master_data = master_data | 0x4000;
@@ -107,28 +140,15 @@
X if (is_slave)
X pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
X restore_flags(flags);
-
- switch(pio) {
- case 4: speed = XFER_PIO_4;break;
- case 3: speed = XFER_PIO_3;break;
- case 2: speed = XFER_PIO_2;break;
- case 1: speed = XFER_PIO_1;break;
- default:
- speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
- break;
- }
-
- err = ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
X }
X
-extern char *ide_xfer_verbose (byte xfer_rate);
-
X static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
X {
X struct hd_driveid *id = drive->id;
X ide_hwif_t *hwif = HWIF(drive);
X struct pci_dev *dev = hwif->pci_dev;
X
+ unsigned long flags;
X int sitre;
X short reg4042, reg44, reg48, reg4a;
X byte speed;
@@ -144,23 +164,22 @@
X pci_read_config_word(dev, 0x48, &reg48);
X pci_read_config_word(dev, 0x4a, &reg4a);
X
-#if PIIX_DEBUG_SET_XFER
- printk("PIIX%s: DMA enable ",
- (dev->device == PCI_DEVICE_ID_INTEL_82371FB_0) ? "a" :
- (dev->device == PCI_DEVICE_ID_INTEL_82371FB_1) ? "b" :
- (dev->device == PCI_DEVICE_ID_INTEL_82371SB_1) ? "3" :
- (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? "4" : " UNKNOWN" );
-#endif /* PIIX_DEBUG_SET_XFER */


+ save_flags(flags);
+ cli();
X

X if (id->dma_ultra && (ultra)) {
X if (!(reg48 & u_flag)) {
X pci_write_config_word(dev, 0x48, reg48|u_flag);
X }
X } else {
- pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+ if (reg48 & u_flag) {
+ pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+ }
X }
X
X if ((id->dma_ultra & 0x0004) && (ultra)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
X if (!((id->dma_ultra >> 8) & 4)) {
X drive->id->dma_ultra &= ~0x0F00;
X drive->id->dma_ultra |= 0x0404;
@@ -171,6 +190,8 @@
X }
X speed = XFER_UDMA_2;
X } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
X if (!((id->dma_ultra >> 8) & 2)) {
X drive->id->dma_ultra &= ~0x0F00;
X drive->id->dma_ultra |= 0x0202;
@@ -182,6 +203,8 @@
X }
X speed = XFER_UDMA_1;
X } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
X if (!((id->dma_ultra >> 8) & 1)) {
X drive->id->dma_ultra &= ~0x0F00;
X drive->id->dma_ultra |= 0x0101;
@@ -193,33 +216,46 @@
X }
X speed = XFER_UDMA_0;
X } else if (id->dma_mword & 0x0004) {
- drive->id->dma_ultra &= ~0x0F0F;
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
X if (!((id->dma_mword >> 8) & 4)) {
X drive->id->dma_mword &= ~0x0F00;
X drive->id->dma_mword |= 0x0404;
X }
X speed = XFER_MW_DMA_2;
X } else if (id->dma_mword & 0x0002) {
- drive->id->dma_ultra &= ~0x0F0F;
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
X if (!((id->dma_mword >> 8) & 2)) {
X drive->id->dma_mword &= ~0x0F00;
X drive->id->dma_mword |= 0x0202;
X }
X speed = XFER_MW_DMA_1;
X } else if (id->dma_1word & 0x0004) {
- drive->id->dma_ultra &= ~0x0F0F;
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_mword &= ~0x0F00;
X if (!((id->dma_1word >> 8) & 4)) {
X drive->id->dma_1word &= ~0x0F00;
X drive->id->dma_1word |= 0x0404;
X }
X speed = XFER_SW_DMA_2;
X } else {
- return ide_dma_off_quietly;
+#if 0
+ speed = XFER_PIO_0;
+#else
+ speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+#endif
X }
X
+ restore_flags(flags);
+ piix_tune_drive(drive, piix_dma_2_pio(speed));
+
X (void) ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
X
X #if PIIX_DEBUG_DRIVE_INFO
@@ -241,7 +277,7 @@
X int ultra = (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0;
X switch (func) {
X case ide_dma_check:
- return piix_config_drive_for_dma(drive, ultra);
+ return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive, ultra), drive);
X default :
X break;
X }
@@ -252,7 +288,7 @@
X void ide_init_piix (ide_hwif_t *hwif)
X {
X hwif->tuneproc = &piix_tune_drive;
-#if PIIX_DMA_PROC
- hwif->dmaproc = &piix_dmaproc;
-#endif /* PIIX_DMA_PROC */
+ if (hwif->dma_base) {
+ hwif->dmaproc = &piix_dmaproc;
+ }
X }
diff -u --recursive --new-file v2.3.5/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.5/linux/drivers/block/rd.c Mon May 17 09:55:21 1999
+++ linux/drivers/block/rd.c Fri Jun 4 01:03:28 1999
@@ -627,7 +627,7 @@
X #ifdef CONFIG_BLK_DEV_INITRD
X __initfunc(void initrd_load(void))
X {
- rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0,0);
+ rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),rd_image_start,0);
X }
X #endif
X
diff -u --recursive --new-file v2.3.5/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c
--- v2.3.5/linux/drivers/char/adbmouse.c Thu Apr 29 12:53:48 1999
+++ linux/drivers/char/adbmouse.c Mon Jun 7 12:12:22 1999
@@ -248,7 +248,7 @@
X {
X mouse.active = 0;
X mouse.ready = 0;
- mouse.wait = NULL;
+ init_waitqueue_head(&mouse.wait);
X
X #ifdef __powerpc__
X if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
diff -u --recursive --new-file v2.3.5/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.5/linux/drivers/char/bttv.c Mon May 31 22:28:05 1999
+++ linux/drivers/char/bttv.c Mon Jun 7 16:17:59 1999
@@ -1,3 +1,4 @@
+
X /*
X bttv - Bt848 frame grabber driver
X
@@ -545,6 +546,8 @@
X { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},
X /* "Leadtek WinView 601", */
X { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}},
+ /* AVEC Intercapture */
+ { 3, 1, 9, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
X };
X #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
X
@@ -2900,6 +2903,18 @@
X I2CWrite(bus, I2C_TEA6300, TEA6300_SW, 0x01, 1); /* mute off input A */
X }
X
+static void init_tea6320(struct i2c_bus *bus)
+{
+ I2CWrite(bus, I2C_TEA6300, TEA6320_V, 0x28, 1); /* master volume */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FFL, 0x28, 1); /* volume left 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FFR, 0x28, 1); /* volume right 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FRL, 0x28, 1); /* volume rear left 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FRR, 0x28, 1); /* volume rear right 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_BA, 0x11, 1); /* bass 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_TR, 0x11, 1); /* treble 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_S, TEA6320_S_GMU, 1); /* mute off input A */
+}
+
X static void init_tda8425(struct i2c_bus *bus)
X {
X I2CWrite(bus, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */
@@ -3027,9 +3042,16 @@
X
X if (I2CRead(&(btv->i2c), I2C_TEA6300) >=0)
X {
+ if(btv->type==BTTV_AVEC_INTERCAP)
+ {
+ printk(KERN_INFO "bttv%d: fader chip: TEA6320\n",btv->nr);
+ btv->audio_chip = TEA6320;
+ init_tea6320(&(btv->i2c));
+ } else {
X printk(KERN_INFO "bttv%d: fader chip: TEA6300\n",btv->nr);
X btv->audio_chip = TEA6300;
X init_tea6300(&(btv->i2c));
+ }
X } else
X printk(KERN_INFO "bttv%d: NO fader chip: TEA6300\n",btv->nr);
X
@@ -3073,6 +3095,9 @@
X case BTTV_WINVIEW_601:
X strcpy(btv->video_dev.name,"BT848(Leadtek WinView 601)");
X break;
+ case BTTV_AVEC_INTERCAP:
+ strcpy(btv->video_dev.name,"(AVEC Intercapture)");
+ break;
X }
X printk("%s\n",btv->video_dev.name);
X audio(btv, AUDIO_MUTE);
diff -u --recursive --new-file v2.3.5/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.3.5/linux/drivers/char/bttv.h Mon May 31 22:28:05 1999
+++ linux/drivers/char/bttv.h Mon Jun 7 16:17:59 1999
@@ -211,6 +211,7 @@
X #define BTTV_ZOLTRIX 0x0f
X #define BTTV_PIXVIEWPLAYTV 0x10
X #define BTTV_WINVIEW_601 0x11
+#define BTTV_AVEC_INTERCAP 0x12
X
X #define AUDIO_TUNER 0x00
X #define AUDIO_RADIO 0x01
@@ -225,6 +226,7 @@
X #define TDA8425 0x02
X #define TDA9840 0x03
X #define TEA6300 0x04
+#define TEA6320 0x05
X
X #define I2C_TSA5522 0xc2
X #define I2C_TDA9840 0x84
@@ -233,7 +235,7 @@
X #define I2C_HAUPEE 0xa0
X #define I2C_STBEE 0xae
X #define I2C_VHX 0xc0
-#define I2C_TEA6300 0x80
+#define I2C_TEA6300 0x80 /* same as TEA6320 */
X
X #define TDA9840_SW 0x00
X #define TDA9840_LVADJ 0x02
@@ -260,6 +262,22 @@
X #define TEA6300_TR 0x03 /* treble control */
X #define TEA6300_FA 0x04 /* fader control */
X #define TEA6300_SW 0x05 /* mute and source switch */
+
+
+#define TEA6320_V 0x00
+#define TEA6320_FFR 0x01 /* volume front right */
+#define TEA6320_FFL 0x02 /* volume front left */
+#define TEA6320_FRR 0x03 /* volume rear right */
+#define TEA6320_FRL 0x04 /* volume rear left */
+#define TEA6320_BA 0x05 /* bass */
+#define TEA6320_TR 0x06 /* treble */
+#define TEA6320_S 0x07 /* switch register */
+ /* values for those registers: */
+#define TEA6320_S_SA 0x01 /* stereo A input */
+#define TEA6320_S_SB 0x02 /* stereo B */
+#define TEA6320_S_SC 0x04 /* stereo C */
+#define TEA6320_S_GMU 0x80 /* general mute */
+
X
X #define PT2254_L_CHANEL 0x10
X #define PT2254_R_CHANEL 0x08
diff -u --recursive --new-file v2.3.5/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.3.5/linux/drivers/char/misc.c Fri Mar 26 13:57:41 1999
+++ linux/drivers/char/misc.c Wed Jun 9 14:44:25 1999
@@ -76,6 +76,7 @@
X extern void dtlk_init(void);
X extern void pcwatchdog_init(void);
X extern int rtc_init(void);
+extern int rtc_sun_init(void); /* Combines MK48T02 and MK48T08 */
X extern int rtc_DP8570A_init(void);
X extern int rtc_MK48T08_init(void);
X extern int dsp56k_init(void);
@@ -247,7 +248,10 @@
X #ifdef CONFIG_BVME6000
X rtc_DP8570A_init();
X #endif
-#if defined(CONFIG_RTC) || defined(CONFIG_SUN_MOSTEK_RTC)
+#if defined(CONFIG_SUN_MOSTEK_RTC)
+ rtc_sun_init();
+#endif
+#if defined(CONFIG_RTC)
X rtc_init();
X #endif
X #ifdef CONFIG_ATARI_DSP56K
diff -u --recursive --new-file v2.3.5/linux/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- v2.3.5/linux/drivers/char/radio-cadet.c Fri May 14 18:55:17 1999
+++ linux/drivers/char/radio-cadet.c Mon Jun 7 16:17:59 1999
@@ -1,7 +1,7 @@
X /* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
X *
X * by Fred Gleason <fr...@wava.com>
- * Version 0.3.1
+ * Version 0.3.2
X *
X * (Loosely) based on code for the Aztech radio card by
X *
@@ -557,7 +557,7 @@
X return -EINVAL;
X
X request_region(io,2,"cadet");
- printk(KERN_INFO "ADS Cadet Radio Card at %x\n",io);
+ printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
X return 0;
X }
X
@@ -570,12 +570,11 @@
X
X for(i=0;i<8;i++) {
X io=iovals[i];
- if(check_region(io,2)) {
- return -1;
- }
- cadet_setfreq(1410);
- if(cadet_getfreq()==1410) {
- return io;
+ if(check_region(io,2)>=0) {
+ cadet_setfreq(1410);
+ if(cadet_getfreq()==1410) {
+ return io;
+ }
X }
X }
X return -1;
diff -u --recursive --new-file v2.3.5/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.3.5/linux/drivers/char/rtc.c Fri May 14 18:55:17 1999
+++ linux/drivers/char/rtc.c Wed Jun 9 14:44:25 1999
@@ -32,10 +32,11 @@
X * 1.08 Miquel van Smoorenburg: disallow certain things on the
X * DEC Alpha as the CMOS clock is also used for other things.
X * 1.09 Nikita Schmidt: epoch support and some Alpha cleanup.
+ * 1.09a Pete Zaitcev: Sun SPARC
X *
X */
X
-#define RTC_VERSION "1.09"
+#define RTC_VERSION "1.09a"
X
X #define RTC_IRQ 8 /* Can't see this changing soon. */
X #define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */
@@ -62,6 +63,12 @@
X #include <asm/uaccess.h>
X #include <asm/system.h>
X
+#ifdef __sparc__
+#include <asm/ebus.h>
+
+static unsigned long rtc_port;
+#endif
+
X /*
X * We sponge a minor off of the misc major. No need slurping
X * up another valuable major dev number for this. If you add
@@ -83,12 +90,12 @@
X
X static unsigned int rtc_poll(struct file *file, poll_table *wait);
X
-void get_rtc_time (struct rtc_time *rtc_tm);
-void get_rtc_alm_time (struct rtc_time *alm_tm);
-void rtc_dropped_irq(unsigned long data);
+static void get_rtc_time (struct rtc_time *rtc_tm);
+static void get_rtc_alm_time (struct rtc_time *alm_tm);
+static void rtc_dropped_irq(unsigned long data);
X
-void set_rtc_irq_bit(unsigned char bit);
-void mask_rtc_irq_bit(unsigned char bit);
+static void set_rtc_irq_bit(unsigned char bit);
+static void mask_rtc_irq_bit(unsigned char bit);
X
X static inline unsigned char rtc_is_updating(void);
X
@@ -525,7 +532,42 @@
X unsigned long uip_watchdog;
X char *guess = NULL;
X #endif
+#ifdef __sparc__
+ struct linux_ebus *ebus;
+ struct linux_ebus_device *edev;
+ int rtc_irq;
+#endif
+
X printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION);
+#ifdef __sparc__
+ for_each_ebus(ebus) {
+ for_each_ebusdev(edev, ebus) {
+ if(strcmp(edev->prom_name, "rtc") == 0) {
+ goto found;
+ }
+ }
+ }
+ printk("rtc_init: no PC rtc found\n");
+ return -EIO;
+
+found:
+ rtc_port = edev->base_address[0];
+ rtc_irq = edev->irqs[0];
+ /*
+ * XXX Interrupt pin #7 in Espresso is shared between RTC and
+ * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here
+ * is asking for trouble with add-on boards. Change to SA_SHIRQ.
+ */
+ if(request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
+ /*
+ * Standard way for sparc to print irq's is to use
+ * __irq_itoa(). I think for EBus it's ok to use %d.
+ */
+ printk("rtc: cannot register IRQ %d\n", rtc_irq);
+ return -EIO;
+ }
+ misc_register(&rtc_dev);
+#else
X if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL))
X {
X /* Yeah right, seeing as irq 8 doesn't even hit the bus. */
@@ -535,6 +577,7 @@
X misc_register(&rtc_dev);
X /* Check region? Naaah! Just snarf it up. */
X request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
+#endif /* __sparc__ vs. others */
X #ifdef __alpha__
X rtc_freq = HZ;
X
@@ -588,7 +631,7 @@
X * for something that requires a steady > 1KHz signal anyways.)
X */
X
-void rtc_dropped_irq(unsigned long data)
+static void rtc_dropped_irq(unsigned long data)


X {
X unsigned long flags;

X
@@ -696,7 +739,7 @@
X return uip;
X }
X
-void get_rtc_time(struct rtc_time *rtc_tm)
+static void get_rtc_time(struct rtc_time *rtc_tm)
X {
X
X unsigned long flags, uip_watchdog = jiffies;
@@ -753,7 +796,7 @@
X rtc_tm->tm_mon--;
X }
X
-void get_rtc_alm_time(struct rtc_time *alm_tm)
+static void get_rtc_alm_time(struct rtc_time *alm_tm)


X {
X unsigned long flags;

X unsigned char ctrl;
@@ -803,7 +846,7 @@
X rtc_irq_data = 0;
X }
X
-void set_rtc_irq_bit(unsigned char bit)
+static void set_rtc_irq_bit(unsigned char bit)
X {
X unsigned char val;
X unsigned long flags;
diff -u --recursive --new-file v2.3.5/linux/drivers/char/tuner.c linux/drivers/char/tuner.c
--- v2.3.5/linux/drivers/char/tuner.c Sun Jan 17 18:28:06 1999
+++ linux/drivers/char/tuner.c Mon Jun 7 16:17:59 1999
@@ -84,7 +84,9 @@
X // 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
X 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,0xc2,623},
X {"Temic 4036 FY5 NTSC", TEMIC, NTSC,
- 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
+ 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
+ {"Alps HSBH1", TEMIC, NTSC,
+ 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,0xc2,732},
X };
X
X /* ---------------------------------------------------------------------- */
diff -u --recursive --new-file v2.3.5/linux/drivers/char/tuner.h linux/drivers/char/tuner.h
--- v2.3.5/linux/drivers/char/tuner.h Sun Nov 8 14:36:46 1998
+++ linux/drivers/char/tuner.h Mon Jun 7 16:17:59 1999
@@ -31,6 +31,7 @@
X #define TUNER_TEMIC_NTSC 6
X #define TUNER_TEMIC_PAL_I 7
X #define TUNER_TEMIC_4036FY5_NTSC 8
+#define TUNER_ALPS_TSBH1_NTSC 9
X
X #define NOTUNER 0
X #define PAL 1
diff -u --recursive --new-file v2.3.5/linux/drivers/i2o/Config.in linux/drivers/i2o/Config.in
--- v2.3.5/linux/drivers/i2o/Config.in Wed Dec 31 16:00:00 1969
+++ linux/drivers/i2o/Config.in Wed Jun 2 14:47:42 1999
@@ -0,0 +1,12 @@
+mainmenu_option next_comment
+comment 'I2O device support'
+
+tristate 'I2O support' CONFIG_I2O
+
+dep_tristate 'I2O PCI support' CONFIG_I2O_PCI $CONFIG_I2O
+dep_tristate 'I2O Block OSM' CONFIG_I2O_BLOCK $CONFIG_I2O
+dep_tristate 'I2O LAN OSM' CONFIG_I2O_LAN $CONFIG_I2O
+dep_tristate 'I2O SCSI OSM' CONFIG_I2O_SCSI $CONFIG_I2O
+dep_tristate 'I2O /proc support' CONFIG_I2O_PROC $CONFIG_I2O
+
+endmenu
diff -u --recursive --new-file v2.3.5/linux/drivers/i2o/Makefile linux/drivers/i2o/Makefile
--- v2.3.5/linux/drivers/i2o/Makefile Wed Dec 31 16:00:00 1969
+++ linux/drivers/i2o/Makefile Wed Jun 2 14:40:22 1999
@@ -0,0 +1,75 @@
+#
+# Makefile for the kernel I2O OSM.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now inherited from the
+# parent makefile.
+#
+
+#
+# Note : at this point, these files are compiled on all systems.
+# In the future, some of these should be built conditionally.
+#
+
+SUB_DIRS :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+
+L_TARGET := i2o.a
+L_OBJS :=
+M_OBJS :=
+
+ifeq ($(CONFIG_I2O_PCI),y)
+L_OBJS += i2o_pci.o
+else
+ ifeq ($(CONFIG_I2O_PCI),m)
+ M_OBJS += i2o_pci.o
+ endif
+endif
+
+ifeq ($(CONFIG_I2O),y)
+LX_OBJS += i2o_core.o i2o_config.o
+else
+ ifeq ($(CONFIG_I2O),m)
+ MX_OBJS += i2o_core.o i2o_config.o
+ endif
+endif
+
+ifeq ($(CONFIG_I2O_BLOCK),y)
+LX_OBJS += i2o_block.o
+else
+ ifeq ($(CONFIG_I2O_BLOCK),m)
+ MX_OBJS += i2o_block.o
+ endif
+endif
+
+ifeq ($(CONFIG_I2O_LAN),y)
+LX_OBJS += i2o_lan.o
+else
+ ifeq ($(CONFIG_I2O_LAN),m)
+ MX_OBJS += i2o_lan.o
+ endif
+endif
+
+ifeq ($(CONFIG_I2O_SCSI),y)
+LX_OBJS += i2o_scsi.o
+else
+ ifeq ($(CONFIG_I2O_SCSI),m)
+ MX_OBJS += i2o_scsi.o
+ endif
+endif
+
+ifeq ($(CONFIG_I2O_PROC),y)
+LX_OBJS += i2o_proc.o
+else
+ ifeq ($(CONFIG_I2O_PROC),m)
+ MX_OBJS += i2o_proc.o
+ endif
+endif
+
+include $(TOPDIR)/Rules.make
+
diff -u --recursive --new-file v2.3.5/linux/drivers/i2o/README linux/drivers/i2o/README
--- v2.3.5/linux/drivers/i2o/README Wed Dec 31 16:00:00 1969
+++ linux/drivers/i2o/README Wed Jun 2 14:40:22 1999
@@ -0,0 +1,78 @@
+
+ Linux I2O Support (c) Copyright 1999 Red Hat Software
+ and others.
+
+ 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.
+
+AUTHORS (so far)
+
+Alan Cox, Building Number Three Ltd.
+ Core code, SCSI and Block OSMs
+
+Steve Ralston, LSI Logic Corp.
+ Debugging SCSI and Block OSM
+
+Deepak Saxena, Intel Corp.
+ /proc interface, bug fixes
+ Ioctl interfaces for control
+
+Philip Rumpf
+ Fixed assorted dumb SMP locking bugs
+
+Juha Sievanen, University Of Helsinki Finland
+ LAN OSM
+ Bug fixes
+ Core code extensions
+
+CREDITS
+
+ This work was made possible by
+
+Red Hat Software
+ Funding for the Building #3 part of the project
+
+Symbios Logic (Now LSI)
+ Host adapters, hints, known to work platforms when I hit
+ compatibility problems
+
+BoxHill Corporation
+ Loan of initial FibreChannel disk array used for development work.
+
+STATUS:
+
+o The core setup works within limits.
+o The scsi layer seems to almost work. I'm still chasing down the hang
+ bug.
+o The block OSM is fairly minimal but does seem to work.
+
+
+TO DO:
+
+General:
+o Support multiple IOP's and tell them about each other
+o Provide hidden address space if asked
+o Long term message flow control
+o PCI IOP's without interrupts are not supported yet
+o Push FAIL handling into the core
+o DDM control interfaces for module load etc
+
+Block:
+o Real error handler
+o Multiple major numbers
+o Read ahead and cache handling stuff. Talk to Ingo and people
+o Power management
+o Finish Media changers
+
+SCSI:
+o Find the right way to associate drives/luns/busses
+
+Net:
+o Port the existing RCPCI work to the frame work or write a new
+ driver. This one is with the Finns
+
+Tape:
+o Anyone seen anything implementing this ?
+
diff -u --recursive --new-file v2.3.5/linux/drivers/i2o/README.ioctl linux/drivers/i2o/README.ioctl
--- v2.3.5/linux/drivers/i2o/README.ioctl Wed Dec 31 16:00:00 1969
+++ linux/drivers/i2o/README.ioctl Wed Jun 2 14:40:22 1999
@@ -0,0 +1,398 @@
+
+Linux I2O User Space Interface
+rev 0.3 - 04/20/99
+
+=============================================================================
+Originally written by Deepak Saxena(deepak...@intel.com)
+Currently maintained by Deepak Saxena(deepak...@intel.com)
+=============================================================================
+
+I. Introduction
+
+The Linux I2O susbsytem provides a set of ioctl() commands than can be
+utilized by user space applications to communicate with IOPs and devices
+on individual IOPs. This document defines the specific ioctl() commands
+that are available to the user and provides examples of their uses.
+
+This document assumes the reader is familiar with or has access to the
+I2O specification as no I2O message parameters are outlined. For information
+on the specification, see http://www.i2osig.org
+
+This document and the I2O user space interface are currently maintained
+by Deepak Saxena. Please send all comments, errata, and bug fixes to
+deepak...@intel.com
+
+II. IOP Access
+
+Access to the I2O subsystem is provided through the device file named
+/dev/i2octl. This file is a character file with major number 10 and minor
+number 166. It can be created through the following command:
+
+ mknod /dev/i2octl c 10 166
+
+III. Determining the IOP Count
+
+ SYNOPSIS
+
+ ioctl(fd, I2OGETIOPS, int *count);
+
+ u8 count[MAX_I2O_CONTROLLERS];
+
+ DESCRIPTION
+
+ This function returns the system's active IOP table. count should
+ point to a buffer containing MAX_I2O_CONTROLLERS entries. Upon
+ returning, each entry will contain a non-zero value if the given
+ IOP unit is active, and NULL if it is inactive or non-existent.
+
+ RETURN VALUE.
+
+ Returns 0 if no errors occur, and -1 otherwise. If an error occurs,
+ errno is set appropriately:
+
+ EIO Unkown error
+
+IV. ExecHrtGet Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt);
+
+ struct i2o_cmd_hrtlct
+ {
+ u32 iop; /* IOP unit number */
+ void *resbuf; /* Buffer for result */
+ u32 *reslen; /* Buffer length in bytes */
+ };
+
+ DESCRIPTION
+
+ This function posts an ExecHrtHet message to the IOP specified by
+ hrt->iop and returns the data in the buffer pointed to by hrt->buf
+ The size of the data written is placed into the memory pointed to
+ by hrt->len.
+
+ RETURNS
+
+ This function returns 0 if no errors occur. If an error occurs, -1
+ is returned and errno is set appropriately:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(hrt->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+V. ExecLctNotify Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct);
+
+ struct i2o_cmd_hrtlct
+ {
+ u32 iop; /* IOP unit number */
+ void *resbuf; /* Buffer for result */
+ u32 *reslen; /* Buffer length in bytes */
+ };
+
+ DESCRIPTION
+
+ This function posts an ExecLctGet message to the IOP specified by
+ lct->iop and returns the data in the buffer pointed to by lct->buf
+ The size of the data written is placed into the memory pointed to
+ by lct->reslen.
+
+ RETURNS
+
+ This function returns 0 if no errors occur. If an error occurs, -1
+ is returned and errno is set appropriately:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(lct->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+VI. UtilParamsSet Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops);
+
+ struct i2o_cmd_psetget
+ {
+ u32 iop; /* IOP unit number */
+ u32 tid; /* Target device TID */
+ void *opbuf; /* Operation List buffer */
+ u32 oplen; /* Operation List buffer length in bytes */
+ void *resbuf; /* Result List buffer */
+ u32 *reslen; /* Result List buffer length in bytes */
+ };
+
+ DESCRIPTION
+
+ This function posts a UtilParamsSet message to the device identified
+ by ops->iop and ops->tid. The operation list for the message is
+ sent through the ops->oplen buffer, and the result list is written
+ into the buffer pointed to by ops->oplen. The number of bytes
+ written is placed into *(ops->reslen).
+
+ RETURNS
+
+ The return value is the size in bytes of the data written into
+ ops->resbuf if no errors occur. If an error occurs, -1 is returned
+ and errno is set appropriatly:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(ops->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+ A return value of 0 does not mean that the value was actually
+ changed properly on the IOP. The user should check the result
+ list to determine the specific status of the transaction.
+
+VII. UtilParamsGet Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops);
+
+ struct i2o_parm_setget
+ {
+ u32 iop; /* IOP unit number */
+ u32 tid; /* Target device TID */
+ void *opbuf; /* Operation List buffer */
+ u32 oplen; /* Operation List buffer length in bytes */
+ void *resbuf; /* Result List buffer */
+ u32 *reslen; /* Result List buffer length in bytes */
+ };
+
+ DESCRIPTION
+
+ This function posts a UtilParamsGet message to the device identified
+ by ops->iop and ops->tid. The operation list for the message is
+ sent through the ops->oplen buffer, and the result list is written
+ into the buffer pointed to by ops->oplen. The actual size of data
+ written is placed into *(ops->reslen).
+
+ RETURNS
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(ops->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+ A return value of 0 does not mean that the value was actually
+ properly retreived. The user should check the result list
+ to determine the specific status of the transaction.
+
+VIII. ExecSwDownload Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw);
+
+ struct i2o_sw_xfer
+ {
+ u32 iop; /* IOP unit number */
+ u8 dl_flags; /* DownLoadFlags field */
+ u8 sw_type; /* Software type */
+ u32 sw_id; /* Software ID */
+ void *buf; /* Pointer to software buffer */
+ u32 *swlen; /* Length of software data */
+ u32 *maxfrag; /* Number of fragments */
+ u32 *curfrag; /* Current fragment number */
+ };
+
+ DESCRIPTION
+
+ This function downloads the software pointed to by sw->buf to the
+ iop identified by sw->iop. The DownloadFlags, SwID, and SwType fields
+ of the ExecSwDownload message are filed in with the values of
+ sw->dl_flags, sw->sw_id, and sw->sw_type.
+
+ Once the ioctl() is called and software transfer begins, the
+ user can read the value *(sw->maxfrag) and *(sw->curfrag) to
+ determine the status of the software transfer. As the IOP
+ is very slow when it comes to SW transfers, this can be
+ used by a separate thread to report status to the user. The
+ user _should not_ write to this memory location until the ioctl()
+ has returned.
+
+ RETURNS
+
+ This function returns 0 no errors occur. If an error occurs, -1
+ is returned and errno is set appropriatly:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(ops->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+IX. ExecSwUpload Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw);
+
+ struct i2o_sw_xfer
+ {
+ u32 iop; /* IOP unit number */
+ u8 flags; /* Unused */
+ u8 sw_type; /* Software type */
+ u32 sw_id; /* Software ID */
+ void *buf; /* Pointer to software buffer */
+ u32 *swlen; /* Length in bytes of software */
+ u32 *maxfrag; /* Number of fragments */
+ u32 *curfrag; /* Current fragment number */
+ };
+
+ DESCRIPTION
+
+ This function uploads software from the IOP identified by sw->iop
+ and places it in the buffer pointed to by sw->buf. The SwID, SwType
+ and SwSize fields of the ExecSwDownload message are filed in
+ with the values of sw->sw_id, sw->sw_type, sw->swlen, and. The
+ actual size of the module is written into *(sw->buflen).
+
+ Once the ioctl() is called and software transfer begins, the
+ user can read the value *(sw->maxfrag) and *(sw->curfrag) to
+ determine the status of the software transfer. As the IOP
+ is very slow when it comes to SW transfers, this can be
+ used by a separate thread to report status to the user. The
+ user _should not_ write to this memory location until the ioctl()
+ has returned.
+
+ RETURNS
+
+ This function returns 0 if no errors occur. If an error occurs, -1
+ is returned and errno is set appropriatly:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(ops->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+X. ExecSwRemove Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw);
+
+ struct i2o_sw_xfer
+ {
+ u32 iop; /* IOP unit number */
+ u8 flags; /* Unused */
+ u8 sw_type; /* Software type */
+ u32 sw_id; /* Software ID */
+ void *buf; /* Unused */
+ u32 *swlen; /* Length in bytes of software data */
+ u32 *maxfrag; /* Unused */
+ u32 *curfrag; /* Unused */
+ };
+
+ DESCRIPTION
+
+ This function uploads software from the IOP identified by sw->iop
+ and places it in the buffer pointed to by sw->buf. The SwID, SwType
+ and SwSize fields of the ExecSwDownload message are filed in
+ with the values of sw->dl_flags, sw->sw_id, and sw->sw_type. The
+ actual size of the module is written into *(sw->buflen).
+
+ RETURNS
+
+ This function returns 0 if no errors occur. If an error occurs, -1
+ is returned and errno is set appropriatly:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(ops->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+X. UtilConfigDialog Message
+
+ SYNOPSIS
+
+ ioctl(fd, I2OHTML, struct i2o_html *htquery);
+
+ struct i2o_html
+ {
+ u32 iop; /* IOP unit number */
+ u32 tid; /* Target device ID */
+ u32 page; /* HTML page */
+ void *resbuf; /* Buffer for reply HTML page */
+ u32 *reslen; /* Length in bytes of reply buffer */
+ void *qbuf; /* Pointer to HTTP query string */
+ u32 qlen; /* Length in bytes of query string buffer */
+ };
+
+ DESCRIPTION
+
+ This function posts an UtilConfigDialog message to the device identified
+ by htquery->iop and htquery->tid. The requested HTML page number is
+ provided by the htquery->page field, and the resultant data is stored
+ in the buffer pointed to by htquery->resbuf. If there is an HTTP query
+ string that is to be sent to the device, it should be sent in the buffer
+ pointed to by htquery->qbuf. If there is no query string, this field
+ should be set to NULL. The actual size of the reply received is written
+ into *(htquery->reslen)
+
+ RETURNS
+
+ This function returns 0 if no error occur. If an error occurs, -1
+ is returned and J errno is set appropriatly:
+
+ ETIMEDOUT Timeout waiting for reply message
+ ENOMEM Kernel memory allocation error
+ ENOBUFS Buffer not large enough. If this occurs, the required
+ buffer length is written into *(ops->reslen)
+ EFAULT Invalid user space pointer was passed
+ ENXIO Invalid IOP number
+ EIO Unkown error
+
+XI. Events
+
+ In the process of determining this. Current idea is to have use
+ the select() interface to allow user apps to periodically poll
+ the /dev/i2octl device for events. When select() notifies the user
+ that an event is available, the user would call read() to retrieve
+ a list of all the events that are pending for the specific device.
+
+=============================================================================
+Revision History
+=============================================================================
+
+Rev 0.1 - 04/01/99
+- Initial revision
+
+Rev 0.2 - 04/06/99
+- Changed return values to match UNIX ioctl() standard. Only return values
+ are 0 and -1. All errors are reported through errno.
+- Added summary of proposed possible event interfaces
+
+Rev 0.3 - 04/20/99
+- Changed all ioctls() to use pointers to user data instead of actual data
+- Updated error values to match the code
+
+
diff -u --recursive --new-file v2.3.5/linux/drivers/i2o/README.lan linux/drivers/i2o/README.lan
--- v2.3.5/linux/drivers/i2o/README.lan Wed Dec 31 16:00:00 1969
+++ linux/drivers/i2o/README.lan Wed Jun 2 14:40:22 1999
@@ -0,0 +1,38 @@
+
+ Linux I2O LAN OSM
+ (c) University of Helsinki, Department of Computer Science
+
+ 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.
+
+AUTHORS
+Auvo Häkkinen, Auvo.H...@cs.Helsinki.FI
+Juha Sievänen, Juha.S...@cs.Helsinki.FI
+
+CREDITS
+
+ This work was made possible by
+
+European Committee
+ Funding for the project
+
+SysKonnect
+ Loaning of FDDI cards
+
+ASUSTeK
+ I2O motherboard
+
+STATUS:
+o The FDDI part of LAN OSM is working to some extent.
+o Only packet per bucket is now supported.
+
+TO DO:
+
+LAN:
+o Add support for bactches
+o Find why big packets flow from I2O box out, but don't want to come in
+o Find the bug in i2o_set_multicast_list(), which kills interrupt
+ handler in i2o_wait_reply()
+o Add support for Ethernet, Token Ring, AnyLAN, Fibre Channel
diff -u --recursive --new-file v2.3.5/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.3.5/linux/drivers/i2o/i2o_block.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/i2o/i2o_block.c Wed Jun 2 14:40:22 1999
@@ -0,0 +1,1071 @@
+/*
+ * I2O block device driver.
+ *
+ * (C) Copyright 1999 Red Hat Software
+ *
+ * Written by Alan Cox, Building Number Three Ltd


+ *
+ * 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 is an initial test release. Most of the good code was taken
+ * from the nbd driver by Pavel Machek, who in turn took some of it
+ * from loop.c. Isn't free software great for reusability 8)
+ *
+ * Fixes:
+ * Steve Ralston: Multiple device handling error fixes,
+ * Added a queue depth.
+ */
+
+#include <linux/major.h>
+
+#include <linux/module.h>
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/ioctl.h>
+#include <linux/i2o.h>
+#include <linux/blkdev.h>
+#include <linux/malloc.h>
+#include <linux/hdreg.h>
+
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+
+#define MAJOR_NR I2O_MAJOR
+
+#include <linux/blk.h>
+
+#define MAX_I2OB 16
+
+#define MAX_I2OB_DEPTH 4
+
+/*
+ * Some of these can be made smaller later
+ */
+
+static int i2ob_blksizes[MAX_I2OB<<4];
+static int i2ob_hardsizes[MAX_I2OB<<4];
+static int i2ob_sizes[MAX_I2OB<<4];
+static int i2ob_media_change_flag[MAX_I2OB];
+static u32 i2ob_max_sectors[MAX_I2OB<<4];
+
+static int i2ob_context;
+
+#ifdef __SMP__
+static spinlock_t i2ob_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
+struct i2ob_device
+{
+ struct i2o_controller *controller;
+ struct i2o_device *i2odev;
+ int tid;
+ int flags;
+ int refcnt;
+ struct request *head, *tail;
+ int done_flag;
+};
+
+/*
+ * Each I2O disk is one of these.
+ */
+
+static struct i2ob_device i2ob_dev[MAX_I2OB<<4];
+static int i2ob_devices = 0;
+static struct hd_struct i2ob[MAX_I2OB<<4];
+static struct gendisk i2ob_gendisk; /* Declared later */
+
+static atomic_t queue_depth; /* For flow control later on */
+
+#define DEBUG( s )
+/* #define DEBUG( s ) printk( s )
+ */
+
+static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int);
+static void i2ob_end_request(struct request *);
+static void do_i2ob_request(void);
+
+/*
+ * Get a message
+ */
+
+static u32 i2ob_get(struct i2ob_device *dev)
+{
+ struct i2o_controller *c=dev->controller;
+ return I2O_POST_READ32(c);
+}
+
+/*
+ * Turn a Linux block request into an I2O block read/write.
+ */
+
+static int i2ob_send(u32 m, struct i2ob_device *dev, struct request *req, u32 base, int unit)
+{
+ struct i2o_controller *c = dev->controller;
+ int tid = dev->tid;
+ u32 *msg;
+ u32 *mptr;
+ u64 offset;
+ struct buffer_head *bh = req->bh;
+ static int old_qd = 2;
+ int count = req->nr_sectors<<9;
+
+ /*
+ * Build a message
+ */
+
+ msg = bus_to_virt(c->mem_offset + m);
+
+ msg[2] = i2ob_context|(unit<<8);
+ msg[3] = (u32)req; /* 64bit issue again here */
+ msg[5] = req->nr_sectors << 9;
+
+ /* This can be optimised later - just want to be sure its right for
+ starters */
+ offset = ((u64)(req->sector+base)) << 9;
+ msg[6] = offset & 0xFFFFFFFF;
+ msg[7] = (offset>>32);
+ mptr=msg+8;
+
+ if(req->cmd == READ)
+ {
+ msg[1] = I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid;
+ /* We don't yet do cache/readahead and other magic */
+ msg[4] = 1<<16;
+ while(bh!=NULL)
+ {
+ *mptr++ = 0x10000000|(bh->b_size);
+ *mptr++ = virt_to_bus(bh->b_data);
+ count -= bh->b_size;
+ bh = bh->b_reqnext;
+ }
+ }
+ else if(req->cmd == WRITE)
+ {
+ msg[1] = I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid;
+ msg[4] = 1<<16;
+ while(bh!=NULL)
+ {
+ *mptr++ = 0x14000000|(bh->b_size);
+ count -= bh->b_size;
+ *mptr++ = virt_to_bus(bh->b_data);
+ bh = bh->b_reqnext;
+ }
+ }
+ mptr[-2]|= 0xC0000000;
+ msg[0] = I2O_MESSAGE_SIZE(mptr-msg) | SGL_OFFSET_8;
+
+ if(req->current_nr_sectors > 8)
+ printk("Gathered sectors %ld.\n",
+ req->current_nr_sectors);
+
+ if(count != 0)
+ {
+ printk("Request count botched by %d.\n", count);
+ msg[5] -= count;
+ }
+
+// printk("Send for %p\n", req);
+
+ i2o_post_message(c,m);
+ atomic_inc(&queue_depth);
+ if(atomic_read(&queue_depth)>old_qd)
+ {
+ old_qd=atomic_read(&queue_depth);
+ printk("Depth now %d.\n", old_qd);
+ }
+ return 0;
+}
+
+/*
+ * Remove a request from the _locked_ request list. We update both the
+ * list chain and if this is the last item the tail pointer.
+ */
+
+static void i2ob_unhook_request(struct i2ob_device *dev, struct request *req)
+{
+ struct request **p = &dev->head;
+ struct request *nt = NULL;
+ static int crap = 0;
+
+ while(*p!=NULL)
+ {
+ if(*p==req)
+ {
+ if(dev->tail==req)
+ dev->tail = nt;
+ *p=req->next;
+ return;
+ }
+ nt=*p;
+ p=&(nt->next);
+ }
+ if(!crap++)
+ printk("i2o_block: request queue corrupt!\n");
+}
+
+/*
+ * Request completion handler
+ */
+
+static void i2ob_end_request(struct request *req)
+{
+ /*
+ * Loop until all of the buffers that are linked
+ * to this request have been marked updated and
+ * unlocked.
+ */
+ while (end_that_request_first( req, !req->errors, "i2o block" ));
+
+ /*
+ * It is now ok to complete the request.
+ */
+ end_that_request_last( req );
+}
+
+
+/*
+ * OSM reply handler. This gets all the message replies
+ */
+
+static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
+{
+ struct request *req;
+ u8 st;
+ u32 *m = (u32 *)msg;
+ u8 unit = (m[2]>>8)&0xF0; /* low 4 bits are partition */
+
+ if(m[0] & (1<<13))
+ {
+ printk("IOP fail.\n");
+ printk("From %d To %d Cmd %d.\n",
+ (m[1]>>12)&0xFFF,
+ m[1]&0xFFF,
+ m[1]>>24);
+ printk("Failure Code %d.\n", m[4]>>24);
+ if(m[4]&(1<<16))
+ printk("Format error.\n");
+ if(m[4]&(1<<17))
+ printk("Path error.\n");
+ if(m[4]&(1<<18))
+ printk("Path State.\n");
+ if(m[4]&(1<<18))
+ printk("Congestion.\n");
+
+ m=(u32 *)bus_to_virt(m[7]);
+ printk("Failing message is %p.\n", m);
+
+ /* We need to up the request failure count here and maybe
+ abort it */
+ req=(struct request *)m[3];
+ /* Now flush the message by making it a NOP */
+ m[0]&=0x00FFFFFF;
+ m[0]|=(I2O_CMD_UTIL_NOP)<<24;
+ i2o_post_message(c,virt_to_bus(m));
+
+ }
+ else
+ {
+ if(m[2]&0x80000000)
+ {
+ int * ptr = (int *)m[3];
+ if(m[4]>>24)
+ *ptr = -1;
+ else
+ *ptr = 1;
+ return;
+ }
+ /*
+ * Lets see what is cooking. We stuffed the
+ * request in the context.
+ */
+
+ req=(struct request *)m[3];
+ st=m[4]>>24;
+
+ if(st!=0)
+ {
+ printk(KERN_ERR "i2ob: error %08X\n", m[4]);
+ /*
+ * Now error out the request block
+ */
+ req->errors++;
+ }
+ }
+ /*
+ * Dequeue the request.
+ */
+
+ spin_lock(&io_request_lock);
+ spin_lock(&i2ob_lock);
+ i2ob_unhook_request(&i2ob_dev[unit], req);
+ i2ob_end_request(req);
+
+ /*
+ * We may be able to do more I/O
+ */
+
+ atomic_dec(&queue_depth);
+ do_i2ob_request();
+ spin_unlock(&i2ob_lock);
+ spin_unlock(&io_request_lock);
+}
+
+static struct i2o_handler i2o_block_handler =
+{
+ i2o_block_reply,
+ "I2O Block OSM",
+ 0
+};
+
+
+/*
+ * Flush all pending requests as errors. Must call with the queue
+ * locked.
+ */
+
+#if 0
+static void i2ob_clear_queue(struct i2ob_device *dev)
+{
+ struct request *req;
+
+ while (1) {
+ req = dev->tail;
+ if (!req)
+ return;
+ req->errors++;
+ i2ob_end_request(req);
+
+ if (dev->tail == dev->head)
+ dev->head = NULL;
+ dev->tail = dev->tail->next;
+ }
+}
+#endif
+
+/*
+ * The I2O block driver is listed as one of those that pulls the
+ * front entry off the queue before processing it. This is important
+ * to remember here. If we drop the io lock then CURRENT will change
+ * on us. We must unlink CURRENT in this routine before we return, if
+ * we use it.
+ */
+
+static void do_i2ob_request(void)
+{
+ struct request *req;
+ int unit;
+ struct i2ob_device *dev;
+ u32 m;
+
+ while (CURRENT) {
+ /*
+ * On an IRQ completion if there is an inactive
+ * request on the queue head it means it isnt yet
+ * ready to dispatch.
+ */
+ if(CURRENT->rq_status == RQ_INACTIVE)
+ return;
+
+ /*
+ * Queue depths probably belong with some kind of
+ * generic IOP commit control. Certainly its not right
+ * its global!
+ */
+ if(atomic_read(&queue_depth)>=MAX_I2OB_DEPTH)
+ break;
+
+ req = CURRENT;
+ unit = MINOR(req->rq_dev);
+ dev = &i2ob_dev[(unit&0xF0)];
+ /* Get a message */
+ m = i2ob_get(dev);
+ /* No messages -> punt
+ FIXME: if we have no messages, and there are no messages
+ we deadlock now. Need a timer/callback ?? */
+ if(m==0xFFFFFFFF)
+ {
+ printk("i2ob: no messages!\n");
+ break;
+ }
+ req->errors = 0;
+ CURRENT = CURRENT->next;
+ req->next = NULL;
+
+ if (dev->head == NULL) {
+ dev->head = req;
+ dev->tail = req;
+ } else {
+ dev->tail->next = req;
+ dev->tail = req;
+ }
+ i2ob_send(m, dev, req, i2ob[unit].start_sect, (unit&0xF0));
+ }
+}
+
+static void i2ob_request(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&i2ob_lock, flags);
+ do_i2ob_request();
+ spin_unlock_irqrestore(&i2ob_lock, flags);
+}
+
+/*
+ * SCSI-CAM for ioctl geometry mapping
+ * Duplicated with SCSI - this should be moved into somewhere common
+ * perhaps genhd ?
+ */
+
+static void i2o_block_biosparam(
+ unsigned long capacity,
+ unsigned short *cyls,
+ unsigned char *hds,
+ unsigned char *secs)
+{
+ unsigned long heads, sectors, cylinders, temp;
+
+ cylinders = 1024L; /* Set number of cylinders to max */
+ sectors = 62L; /* Maximize sectors per track */
+
+ temp = cylinders * sectors; /* Compute divisor for heads */
+ heads = capacity / temp; /* Compute value for number of heads */
+ if (capacity % temp) { /* If no remainder, done! */
+ heads++; /* Else, increment number of heads */
+ temp = cylinders * heads; /* Compute divisor for sectors */
+ sectors = capacity / temp; /* Compute value for sectors per
+ track */
+ if (capacity % temp) { /* If no remainder, done! */
+ sectors++; /* Else, increment number of sectors */
+ temp = heads * sectors; /* Compute divisor for cylinders */
+ cylinders = capacity / temp;/* Compute number of cylinders */
+ }
+ }
+ /* if something went wrong, then apparently we have to return
+ a geometry with more than 1024 cylinders */
+ if (cylinders == 0 || heads > 255 || sectors > 63 || cylinders >1023)
+ {
+ unsigned long temp_cyl;
+
+ heads = 64;
+ sectors = 32;
+ temp_cyl = capacity / (heads * sectors);
+ if (temp_cyl > 1024)
+ {
+ heads = 255;
+ sectors = 63;
+ }
+ cylinders = capacity / (heads * sectors);
+ }
+ *cyls = (unsigned int) cylinders; /* Stuff return values */
+ *secs = (unsigned int) sectors;
+ *hds = (unsigned int) heads;
+}
+
+/*
+ * Rescan the partition tables
+ */
+
+static int do_i2ob_revalidate(kdev_t dev, int maxu)
+{
+ int minor=MINOR(dev);
+ int i;
+
+ minor&=0xF0;
+
+ i2ob_dev[minor].refcnt++;
+ if(i2ob_dev[minor].refcnt>maxu+1)
+ {
+ i2ob_dev[minor].refcnt--;
+ return -EBUSY;
+ }
+
+ for( i = 15; i>=0 ; i--)
+ {
+ int m = minor+i;
+ kdev_t d = MKDEV(MAJOR_NR, m);
+ struct super_block *sb = get_super(d);
+
+ sync_dev(d);
+ if(sb)
+ invalidate_inodes(sb);
+ invalidate_buffers(d);
+ i2ob_gendisk.part[m].start_sect = 0;
+ i2ob_gendisk.part[m].nr_sects = 0;
+ }
+
+ /*
+ * Do a physical check and then reconfigure
+ */
+
+ i2ob_install_device(i2ob_dev[minor].controller, i2ob_dev[minor].i2odev,
+ minor);
+ i2ob_dev[minor].refcnt--;
+ return 0;
+}
+
+/*
+ * Issue device specific ioctl calls.
+ */
+
+static int i2ob_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct i2ob_device *dev;
+ int minor;
+
+ /* Anyone capable of this syscall can do *real bad* things */
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!inode)
+ return -EINVAL;
+ minor = MINOR(inode->i_rdev);
+ if (minor >= (MAX_I2OB<<4))
+ return -ENODEV;
+
+ dev = &i2ob_dev[minor];
+ switch (cmd) {
+ case BLKRASET:
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if(arg > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = arg;
+ return 0;
+
+ case BLKRAGET:
+ if (!arg) return -EINVAL;
+ return put_user(read_ahead[MAJOR(inode->i_rdev)],
+ (long *) arg);
+ case BLKGETSIZE:
+ return put_user(i2ob[minor].nr_sects, (long *) arg);
+
+ case BLKFLSBUF:
+ if(!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ fsync_dev(inode->i_rdev);
+ invalidate_buffers(inode->i_rdev);
+ return 0;
+
+ case HDIO_GETGEO:
+ {
+ struct hd_geometry g;
+ int u=minor&0xF0;
+ i2o_block_biosparam(i2ob_sizes[u]<<1,
+ &g.cylinders, &g.heads, &g.sectors);
+ g.start = i2ob[minor].start_sect;
+ return copy_to_user((void *)arg,&g, sizeof(g))?-EFAULT:0;
+ }
+
+ case BLKRRPART:
+ if(!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return do_i2ob_revalidate(inode->i_rdev,1);
+
+ default:
+ return blk_ioctl(inode->i_rdev, cmd, arg);
+ }
+}
+
+/*
+ * Issue UTIL_CLAIM messages
+ */
+
+static int i2ob_claim_device(struct i2ob_device *dev, int onoff)
+{
+ return i2o_issue_claim(dev->controller, dev->tid, i2ob_context, onoff, &dev->done_flag);
+}
+
+/*
+ * Close the block device down
+ */
+
+static int i2ob_release(struct inode *inode, struct file *file)
+{
+ struct i2ob_device *dev;
+ int minor;
+
+ minor = MINOR(inode->i_rdev);
+ if (minor >= (MAX_I2OB<<4))
+ return -ENODEV;
+ sync_dev(inode->i_rdev);
+ dev = &i2ob_dev[(minor&0xF0)];
+ if (dev->refcnt <= 0)
+ printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt);
+ dev->refcnt--;
+ if(dev->refcnt==0)
+ {
+ /*
+ * Flush the onboard cache on unmount
+ */
+ u32 msg[5];
+ int *query_done = &dev->done_flag;
+ msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid;
+ msg[2] = i2ob_context|0x80000000;
+ msg[3] = (u32)query_done;
+ msg[4] = 60<<16;
+ i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+ /*
+ * Unlock the media
+ */
+ msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid;
+ msg[2] = i2ob_context|0x80000000;
+ msg[3] = (u32)query_done;
+ msg[4] = -1;
+ i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+
+ /*
+ * Now unclaim the device.
+ */
+ if (i2ob_claim_device(dev, 0)<0)
+ printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n");
+
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/*
+ * Open the block device.
+ */
+
+static int i2ob_open(struct inode *inode, struct file *file)
+{
+ int minor;
+ struct i2ob_device *dev;
+
+ if (!inode)
+ return -EINVAL;
+ minor = MINOR(inode->i_rdev);
+ if (minor >= MAX_I2OB<<4)
+ return -ENODEV;
+ dev=&i2ob_dev[(minor&0xF0)];
+
+ if(dev->refcnt++==0)
+ {
+ u32 msg[6];
+ int *query_done;
+
+
+ if(i2ob_claim_device(dev, 1)<0)
+ {
+ dev->refcnt--;
+ return -EBUSY;
+ }
+
+ query_done = &dev->done_flag;
+ /*
+ * Mount the media if needed. Note that we don't use
+ * the lock bit. Since we have to issue a lock if it
+ * refuses a mount (quite possible) then we might as


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part11

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


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

+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#define _SK_MCA_DRIVER_
+#include "sk_mca.h"
+
+/* ------------------------------------------------------------------------
+ * global static data - not more since we can handle multiple boards and
+ * have to pack all state info into the device struct!
+ * ------------------------------------------------------------------------ */
+
+static char *MediaNames[Media_Count]=
+ {"10Base2", "10BaseT", "10Base5", "Unknown"};
+
+static unsigned char poly[] =
+ {1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0};
+
+/* ------------------------------------------------------------------------
+ * private subfunctions
+ * ------------------------------------------------------------------------ */
+
+/* dump parts of shared memory - only needed during debugging */
+
+#ifdef DEBUG
+static void dumpmem(struct device *dev, u32 start, u32 len)
+{
+ int z;
+
+ for (z = 0; z < len; z++)
+ {
+ if ((z & 15) == 0)
+ printk("%04x:", z);
+ printk(" %02x", readb(dev->mem_start + start + z));
+ if ((z & 15) == 15)
+ printk("\n");
+ }
+}
+
+/* print exact time - ditto */
+
+static void PrTime(void)
+{
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec);
+}
+#endif
+
+/* deduce resources out of POS registers */
+
+static void getaddrs(int slot, int junior, int *base, int *irq,
+ skmca_medium *medium)
+{
+ u_char pos0, pos1, pos2;
+
+ if (junior)
+ {
+ pos0 = mca_read_stored_pos(slot, 2);
+ *base = ((pos0 & 0x0e) << 13) + 0xc0000;
+ *irq = ((pos0 & 0x10) >> 4) + 10;
+ *medium = Media_Unknown;
+ }
+ else
+ {
+ /* reset POS 104 Bits 0+1 so the shared memory region goes to the
+ configured area between 640K and 1M. Afterwards, enable the MC2.
+ I really don't know what rode SK to do this... */
+
+ mca_write_pos(slot, 4, mca_read_stored_pos(slot, 4) & 0xfc);
+ mca_write_pos(slot, 2, mca_read_stored_pos(slot, 2) | 0x01);
+
+ pos1 = mca_read_stored_pos(slot, 3);
+ pos2 = mca_read_stored_pos(slot, 4);
+ *base = ((pos1 & 0x07) << 14) + 0xc0000;
+ switch (pos2 & 0x0c)
+ {
+ case 0: *irq = 3; break;
+ case 4: *irq = 5; break;
+ case 8: *irq = 10; break;
+ case 12: *irq = 11; break;
+ }
+ *medium = (pos2 >> 6) & 3;
+ }
+}
+
+/* check for both cards:
+ When the MC2 is turned off, it was configured for more than 15MB RAM,
+ is disabled and won't get detected using the standard probe. We
+ therefore have to scan the slots manually :-( */
+
+static int dofind(int *junior, int firstslot)
+{
+ int slot;
+ unsigned int id;
+
+ for (slot = firstslot; slot < MCA_MAX_SLOT_NR; slot++)
+ {
+ id = mca_read_stored_pos(slot, 0)
+ + (((unsigned int) mca_read_stored_pos(slot, 1)) << 8);
+
+ *junior = 0;
+ if (id == SKNET_MCA_ID)
+ return slot;
+ *junior = 1;
+ if (id == SKNET_JUNIOR_MCA_ID)
+ return slot;
+ }
+ return MCA_NOTFOUND;
+}
+
+/* reset the whole board */
+
+static void ResetBoard(struct device *dev)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+
+ writeb(CTRL_RESET_ON, priv->ctrladdr);
+ udelay(10);
+ writeb(CTRL_RESET_OFF, priv->ctrladdr);
+}
+
+/* set LANCE register - must be atomic */
+
+static void SetLANCE(struct device *dev, u16 addr, u16 value)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;


+ unsigned long flags;
+

+ /* disable interrupts */


+
+ save_flags(flags);
+ cli();

+
+ /* wait until no transfer is pending */
+
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+ /* transfer register address to RAP */
+
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+ writew(addr, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+ /* transfer data to register */
+
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, priv->ctrladdr);
+ writew(value, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+ /* reenable interrupts */
+
+ restore_flags(flags);
+}
+
+/* get LANCE register */
+
+static u16 GetLANCE(struct device *dev, u16 addr)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+ unsigned long flags;
+ unsigned int res;
+
+ /* disable interrupts */


+
+ save_flags(flags);
+ cli();

+
+ /* wait until no transfer is pending */
+
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+ /* transfer register address to RAP */
+
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+ writew(addr, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+
+ /* transfer data from register */
+
+ writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, priv->ctrladdr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ res = readw(priv->ioregaddr);
+
+ /* reenable interrupts */
+
+ restore_flags(flags);
+
+ return res;
+}
+
+/* build up descriptors in shared RAM */
+
+static void InitDscrs(struct device *dev)
+{
+ u32 bufaddr;
+
+ /* Set up Tx descriptors. The board has only 16K RAM so bits 16..23
+ are always 0. */
+
+ bufaddr = RAM_DATABASE;
+ {
+ LANCE_TxDescr descr;
+ int z;
+
+ for (z = 0; z < TXCOUNT; z++)
+ {
+ descr.LowAddr = bufaddr;
+ descr.Flags = 0;
+ descr.Len = 0xf000;
+ descr.Status = 0;
+ memcpy_toio(dev->mem_start + RAM_TXBASE + (z * sizeof(LANCE_TxDescr)),
+ &descr, sizeof(LANCE_TxDescr));
+ memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
+ bufaddr += RAM_BUFSIZE;
+ }
+ }
+
+ /* do the same for the Rx descriptors */
+
+ {
+ LANCE_RxDescr descr;
+ int z;
+
+ for (z = 0; z < RXCOUNT; z++)
+ {
+ descr.LowAddr = bufaddr;
+ descr.Flags = RXDSCR_FLAGS_OWN;
+ descr.MaxLen = -RAM_BUFSIZE;
+ descr.Len = 0;
+ memcpy_toio(dev->mem_start + RAM_RXBASE + (z * sizeof(LANCE_RxDescr)),
+ &descr, sizeof(LANCE_RxDescr));
+ memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
+ bufaddr += RAM_BUFSIZE;
+ }
+ }
+}
+
+/* calculate the hash bit position for a given multicast address
+ taken more or less directly from the AMD datasheet... */
+
+static void UpdateCRC(unsigned char *CRC, int bit)
+{
+ int j;
+
+ /* shift CRC one bit */
+
+ memmove(CRC + 1, CRC, 32 * sizeof(unsigned char));
+ CRC[0] = 0;
+
+ /* if bit XOR controlbit = 1, set CRC = CRC XOR polynomial */
+
+ if (bit ^ CRC[32])
+ for (j = 0; j < 32; j++)
+ CRC[j] ^= poly[j];
+}
+
+static unsigned int GetHash(char *address)
+{
+ unsigned char CRC[33];
+ int i, byte, hashcode;
+
+ /* a multicast address has bit 0 in the first byte set */
+
+ if ((address[0] & 1) == 0)
+ return -1;
+
+ /* initialize CRC */
+
+ memset(CRC, 1, sizeof(CRC));
+
+ /* loop through address bits */
+
+ for (byte = 0; byte < 6; byte++)
+ for (i = 0; i < 8; i++)
+ UpdateCRC(CRC, (address[byte] >> i) & 1);
+
+ /* hashcode is the 6 least significant bits of the CRC */
+
+ hashcode = 0;
+ for (i = 0; i < 6; i++)
+ hashcode = (hashcode << 1) + CRC[i];
+ return hashcode;
+}
+
+/* feed ready-built initialization block into LANCE */
+
+static void InitLANCE(struct device *dev)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+
+ /* build up descriptors. */
+
+ InitDscrs(dev);
+
+ /* next RX descriptor to be read is the first one. Since the LANCE
+ will start from the beginning after initialization, we have to
+ reset out pointers too. */
+
+ priv->nextrx = 0;
+
+ /* no TX descriptors active */
+
+ priv->nexttxput = priv->nexttxdone = priv->txbusy = 0;
+
+ /* set up the LANCE bus control register - constant for SKnet boards */
+
+ SetLANCE(dev, LANCE_CSR3, CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD);
+
+ /* write address of initialization block into LANCE */
+
+ SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff);
+ SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff);
+
+ /* we don't get ready until the LANCE has read the init block */
+
+ dev->tbusy = 1;
+
+ /* let LANCE read the initialization block. LANCE is ready
+ when we receive the corresponding interrupt. */
+
+ SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT);
+}
+
+/* stop the LANCE so we can reinitialize it */
+
+static void StopLANCE(struct device *dev)
+{
+ /* can't take frames any more */
+
+ dev->tbusy = 1;
+
+ /* disable interrupts, stop it */
+
+ SetLANCE(dev, LANCE_CSR0, CSR0_STOP);
+}
+
+/* initialize card and LANCE for proper operation */
+
+static void InitBoard(struct device *dev)
+{
+ LANCE_InitBlock block;
+
+ /* Lay out the shared RAM - first we create the init block for the LANCE.
+ We do not overwrite it later because we need it again when we switch
+ promiscous mode on/off. */
+
+ block.Mode = 0;
+ if (dev->flags & IFF_PROMISC)
+ block.Mode |= LANCE_INIT_PROM;
+ memcpy(block.PAdr, dev->dev_addr, 6);
+ memset(block.LAdrF, 0, sizeof(block.LAdrF));
+ block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
+ block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
+
+ memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+
+ /* initialize LANCE. Implicitly sets up other structures in RAM. */
+
+ InitLANCE(dev);
+}
+
+/* deinitialize card and LANCE */
+
+static void DeinitBoard(struct device *dev)
+{
+ /* stop LANCE */
+
+ StopLANCE(dev);
+
+ /* reset board */
+
+ ResetBoard(dev);
+}
+
+/* ------------------------------------------------------------------------
+ * interrupt handler(s)
+ * ------------------------------------------------------------------------ */
+
+/* LANCE has read initializazion block -> start it */
+
+static u16 irqstart_handler(struct device *dev, u16 oldcsr0)
+{
+ /* now we're ready to transmit */
+
+ dev->tbusy = 0;
+
+ /* reset IDON bit, start LANCE */
+
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT);
+ return GetLANCE(dev, LANCE_CSR0);
+}
+
+/* receive interrupt */
+
+static u16 irqrx_handler(struct device *dev, u16 oldcsr0)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+ LANCE_RxDescr descr;
+ unsigned int descraddr;
+
+ /* did we loose blocks due to a FIFO overrun ? */
+
+ if (oldcsr0 & CSR0_MISS)
+ priv->stat.rx_fifo_errors++;
+
+ /* run through queue until we reach a descriptor we do not own */
+
+ descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
+ while (1)
+ {
+ /* read descriptor */
+ memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_RxDescr));
+
+ /* if we reach a descriptor we do not own, we're done */
+ if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)
+ break;
+
+#ifdef DEBUG
+ PrTime(); printk("Receive packet on descr %d len %d\n", priv->nextrx, descr.Len);
+#endif
+
+ /* erroneous packet ? */
+ if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0)
+ {
+ priv->stat.rx_errors++;
+ if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
+ priv->stat.rx_crc_errors++;
+ else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
+ priv->stat.rx_frame_errors++;
+ else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0)
+ priv->stat.rx_fifo_errors++;
+ }
+
+ /* good packet ? */
+ else
+ {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(descr.Len + 2);
+ if (skb == NULL)
+ priv->stat.rx_dropped++;
+ else
+ {
+ memcpy_fromio(skb_put(skb, descr.Len),
+ dev->mem_start + descr.LowAddr, descr.Len);
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_NONE;
+ priv->stat.rx_packets++;
+#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */
+ priv->stat.rx_bytes += descr.Len;
+#endif
+ netif_rx(skb);
+ }
+ }
+
+ /* give descriptor back to LANCE */
+ descr.Len = 0;
+ descr.Flags |= RXDSCR_FLAGS_OWN;
+
+ /* update descriptor in shared RAM */
+ memcpy_toio(dev->mem_start + descraddr, &descr, sizeof(LANCE_RxDescr));
+
+ /* go to next descriptor */
+ priv->nextrx++; descraddr += sizeof(LANCE_RxDescr);
+ if (priv->nextrx >= RXCOUNT)
+ {
+ priv->nextrx = 0;
+ descraddr = RAM_RXBASE;
+ }
+ }
+
+ /* reset RINT bit */
+
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT);
+ return GetLANCE(dev, LANCE_CSR0);
+}
+
+/* transmit interrupt */
+
+static u16 irqtx_handler(struct device *dev, u16 oldcsr0)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+ LANCE_TxDescr descr;
+ unsigned int descraddr;
+
+ /* check descriptors at most until no busy one is left */
+
+ descraddr = RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
+ while (priv->txbusy > 0)
+ {
+ /* read descriptor */
+ memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_TxDescr));
+
+ /* if the LANCE still owns this one, we've worked out all sent packets */
+ if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)
+ break;
+
+#ifdef DEBUG
+ PrTime(); printk("Send packet done on descr %d\n", priv->nexttxdone);
+#endif
+
+ /* update statistics */
+ if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0)
+ {
+ priv->stat.tx_packets++;
+#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */
+ priv->stat.tx_bytes++;
+#endif
+ }
+ else
+ {
+ priv->stat.tx_errors++;
+ if ((descr.Status & TXDSCR_STATUS_UFLO) != 0)
+ {
+ priv->stat.tx_fifo_errors++;
+ InitLANCE(dev);
+ }
+ else if ((descr.Status & TXDSCR_STATUS_LCOL) != 0)
+ priv->stat.tx_window_errors++;
+ else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0)
+ priv->stat.tx_carrier_errors++;
+ else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0)
+ priv->stat.tx_aborted_errors++;
+ }
+
+ /* go to next descriptor */
+ priv->nexttxdone++;
+ descraddr += sizeof(LANCE_TxDescr);
+ if (priv->nexttxdone >= TXCOUNT)
+ {
+ priv->nexttxdone = 0;
+ descraddr = RAM_TXBASE;
+ }
+ priv->txbusy--;
+ }
+
+ /* reset TX interrupt bit */
+
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT);
+ oldcsr0 = GetLANCE(dev, LANCE_CSR0);
+
+ /* at least one descriptor is freed. Therefore we can accept
+ a new one */
+
+ dev->tbusy = 0;
+
+ /* inform upper layers we're in business again */
+
+ mark_bh(NET_BH);
+
+ return oldcsr0;
+}
+
+/* general interrupt entry */
+
+static void irq_handler(int irq, void *device, struct pt_regs *regs)
+{
+ struct device *dev = (struct device*) device;
+ u16 csr0val;
+
+ /* read CSR0 to get interrupt cause */
+
+ csr0val = GetLANCE(dev, LANCE_CSR0);
+
+ /* in case we're not meant... */
+
+ if ((csr0val & CSR0_INTR) == 0)
+ return;
+
+ dev->interrupt = 1;
+
+ /* loop through the interrupt bits until everything is clear */
+
+ do
+ {
+ if ((csr0val & CSR0_IDON) != 0)
+ csr0val = irqstart_handler(dev, csr0val);
+ if ((csr0val & CSR0_RINT) != 0)
+ csr0val = irqrx_handler(dev, csr0val);
+ if ((csr0val & CSR0_TINT) != 0)
+ csr0val = irqtx_handler(dev, csr0val);
+ }
+ while ((csr0val & CSR0_INTR) != 0);
+
+ dev->interrupt = 0;
+}
+
+/* ------------------------------------------------------------------------
+ * driver methods
+ * ------------------------------------------------------------------------ */
+
+/* MCA info */
+
+static int skmca_getinfo(char *buf, int slot, void *d)
+{
+ int len = 0, i;
+ struct device *dev = (struct device*) d;
+ skmca_priv *priv;
+
+ /* can't say anything about an uninitialized device... */
+
+ if (dev == NULL)
+ return len;
+ if (dev->priv == NULL)
+ return len;
+ priv = (skmca_priv*) dev->priv;
+
+ /* print info */
+
+ len += sprintf(buf + len, "IRQ: %d\n", priv->realirq);
+ len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
+ dev->mem_end - 1);
+ len += sprintf(buf + len, "Transceiver: %s\n", MediaNames[priv->medium]);
+ len += sprintf(buf + len, "Device: %s\n", dev->name);
+ len += sprintf(buf + len, "MAC address:");
+ for (i = 0; i < 6; i ++ )
+ len += sprintf( buf+len, " %02x", dev->dev_addr[i] );
+ buf[len++] = '\n';
+ buf[len] = 0;
+
+ return len;
+}
+
+/* open driver. Means also initialization and start of LANCE */
+
+static int skmca_open(struct device *dev)
+{
+ int result;
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+
+ /* register resources - only necessary for IRQ */
+ result = request_irq(priv->realirq, irq_handler, SA_SHIRQ | SA_SAMPLE_RANDOM,
+ "sk_mca", dev);
+ if (result != 0)
+ {
+ printk("%s: failed to register irq %d\n", dev->name, dev->irq);
+ return result;
+ }
+ dev->irq = priv->realirq;
+
+ /* set up the card and LANCE */
+ InitBoard(dev);
+
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif


+
+ return 0;
+}
+

+/* close driver. Shut down board and free allocated resources */
+
+static int skmca_close(struct device *dev)
+{
+ /* turn off board */
+ DeinitBoard(dev);
+
+ /* release resources */
+ if (dev->irq != 0)
+ free_irq(dev->irq, dev);


+ dev->irq = 0;
+

+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif


+
+ return 0;
+}
+

+/* transmit a block. */
+
+static int skmca_tx(struct sk_buff *skb, struct device *dev)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+ LANCE_TxDescr descr;
+ unsigned int address;
+ int tmplen, retval = 0;


+ unsigned long flags;
+

+ /* if we get called with a NULL descriptor, the Ethernet layer thinks
+ our card is stuck an we should reset it. We'll do this completely: */
+
+ if (skb == NULL)
+ {
+ DeinitBoard(dev);
+ InitBoard(dev);
+ return 0; /* don't try to free the block here ;-) */
+ }
+
+ /* is there space in the Tx queue ? If no, the upper layer gave us a
+ packet in spite of us not being ready and is really in trouble.
+ We'll do the dropping for him: */
+ if (priv->txbusy >= TXCOUNT)
+ {
+ priv->stat.tx_dropped++;
+ retval = -EIO;
+ goto tx_done;
+ }
+
+ /* get TX descriptor */
+ address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
+ memcpy_fromio(&descr, dev->mem_start + address, sizeof(LANCE_TxDescr));
+
+ /* enter packet length as 2s complement - assure minimum length */
+ tmplen = skb->len;
+ if (tmplen < 60)
+ tmplen = 60;
+ descr.Len = 65536 - tmplen;
+
+ /* copy filler into RAM - in case we're filling up...
+ we're filling a bit more than necessary, but that doesn't harm
+ since the buffer is far larger... */
+ if (tmplen > skb->len)
+ {
+ char *fill = "NetBSD is a nice OS too! ";
+ unsigned int destoffs = 0, l = strlen(fill);
+
+ while (destoffs < tmplen)
+ {
+ memcpy_toio(dev->mem_start + descr.LowAddr + destoffs, fill, l);
+ destoffs += l;
+ }
+ }
+
+ /* do the real data copying */
+ memcpy_toio(dev->mem_start + descr.LowAddr, skb->data, skb->len);
+
+ /* hand descriptor over to LANCE - this is the first and last chunk */
+ descr.Flags = TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP;
+
+#ifdef DEBUG
+ PrTime(); printk("Send packet on descr %d len %d\n", priv->nexttxput, skb->len);
+#endif
+
+ /* one more descriptor busy */
+ save_flags(flags);
+ cli();
+ priv->nexttxput++;
+ if (priv->nexttxput >= TXCOUNT)
+ priv->nexttxput = 0;
+ priv->txbusy++;
+ dev->tbusy = (priv->txbusy >= TXCOUNT);
+
+ /* write descriptor back to RAM */
+ memcpy_toio(dev->mem_start + address, &descr, sizeof(LANCE_TxDescr));
+
+ /* if no descriptors were active, give the LANCE a hint to read it
+ immediately */
+
+ if (priv->txbusy == 0)
+ SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_TDMD);
+
+ restore_flags(flags);
+
+tx_done:
+
+ /* When did that change exactly ? */
+
+#if LINUX_VERSION_CODE >= 0x020200
+ dev_kfree_skb(skb);
+#else
+ dev_kfree_skb(skb, FREE_WRITE);
+#endif
+ return retval;
+}
+
+/* return pointer to Ethernet statistics */
+
+static struct enet_statistics *skmca_stats(struct device *dev)
+{
+ skmca_priv *priv = (skmca_priv*) dev->priv;
+
+ return &(priv->stat);
+}
+
+/* we don't support runtime reconfiguration, since am MCA card can
+ be unambigously identified by its POS registers. */
+
+static int skmca_config(struct device *dev, struct ifmap *map)


+{
+ return 0;
+}
+

+/* switch receiver mode. We use the LANCE's multicast filter to prefilter
+ multicast addresses. */
+
+static void skmca_set_multicast_list(struct device *dev)
+{
+ LANCE_InitBlock block;
+
+ /* first stop the LANCE... */
+ StopLANCE(dev);
+
+ /* ...then modify the initialization block... */
+ memcpy_fromio(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
+ if (dev->flags & IFF_PROMISC)
+ block.Mode |= LANCE_INIT_PROM;
+ else
+ block.Mode &= ~LANCE_INIT_PROM;
+
+ if (dev->flags & IFF_ALLMULTI) /* get all multicasts */
+ {
+ memset(block.LAdrF, 8, 0xff);
+ }
+ else /* get selected/no multicasts */
+ {
+ struct dev_mc_list *mptr;
+ int code;
+
+ memset(block.LAdrF, 8, 0x00);
+ for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next)
+ {
+ code = GetHash(mptr->dmi_addr);
+ block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);
+ }
+ }
+
+ memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+
+ /* ...then reinit LANCE with the correct flags */
+ InitLANCE(dev);
+}
+
+/* ------------------------------------------------------------------------
+ * hardware check
+ * ------------------------------------------------------------------------ */
+
+#ifdef MODULE
+static int startslot; /* counts through slots when probing multiple devices */
+#else
+#define startslot 0 /* otherwise a dummy, since there is only eth0 in-kern*/
+#endif
+
+int skmca_probe(struct device *dev)
+{
+ int force_detect = 0;
+ int junior, slot, i;
+ int base = 0, irq = 0;
+ skmca_priv *priv;
+ skmca_medium medium;
+
+ /* can't work without an MCA bus ;-) */
+
+ if (MCA_bus == 0)
+ return ENODEV;
+
+ /* start address of 1 --> forced detection */
+
+ if (dev->mem_start == 1)
+ force_detect = 1;
+
+ /* search through slots */
+
+ if (dev != NULL)
+ {
+ base = dev->mem_start;
+ irq = dev->irq;
+ }
+ slot = dofind(&junior, startslot);
+
+ while (slot != -1)
+ {
+ /* deduce card addresses */
+
+ getaddrs(slot, junior, &base, &irq, &medium);
+
+#if 0
+ /* this should work, but it doesn't with 2.2.9 :-(
+ somehow 'mca_is_adapter_used()' is missing in kernel syms... */
+#if LINUX_VERSION_CODE >= 0x020200
+ /* slot already in use ? */
+
+ if (mca_is_adapter_used(slot))
+ {
+ slot = dofind(&junior, slot + 1);
+ continue;
+ }
+#endif
+#endif
+
+ /* were we looking for something different ? */
+
+ if ((dev->irq != 0) || (dev->mem_start != 0))
+ {
+ if ((dev->irq != 0) && (dev->irq != irq))
+ {
+ slot = dofind(&junior, slot + 1);
+ continue;
+ }
+ if ((dev->mem_start != 0) && (dev->mem_start != base))
+ {
+ slot = dofind(&junior, slot + 1);
+ continue;
+ }
+ }
+
+ /* found something that matches */
+
+ break;
+ }
+
+ /* nothing found ? */
+
+ if (slot == -1)
+ return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV;
+
+ /* make procfs entries */
+
+ if (junior)
+ mca_set_adapter_name(slot, "SKNET junior MC2 Ethernet Adapter");
+ else
+ mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");
+ mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);
+
+#if LINUX_VERSION_CODE >= 0x020200
+ mca_mark_as_used(slot);
+#endif
+
+ /* announce success */
+ printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
+ junior ? "Junior MC2" : "MC2+", slot + 1);
+
+ /* allocate structure */
+ priv = dev->priv = (skmca_priv*) kmalloc(sizeof(skmca_priv), GFP_KERNEL);
+ priv->slot = slot;
+ priv->macbase = base + 0x3fc0;
+ priv->ioregaddr = base + 0x3ff0;
+ priv->ctrladdr = base + 0x3ff2;
+ priv->cmdaddr = base + 0x3ff3;
+ priv->realirq = irq;
+ priv->medium = medium;
+ memset(&(priv->stat), 0, sizeof(struct enet_statistics));
+
+ /* set base + irq for this device (irq not allocated so far) */


+ dev->irq = 0;

+ dev->mem_start = base;
+ dev->mem_end = base + 0x4000;
+
+ /* set methods */
+ dev->open = skmca_open;
+ dev->stop = skmca_close;
+ dev->set_config = skmca_config;
+ dev->hard_start_xmit = skmca_tx;
+ dev->do_ioctl = NULL;
+ dev->get_stats = skmca_stats;
+ dev->set_multicast_list = skmca_set_multicast_list;
+ dev->flags |= IFF_MULTICAST;
+
+ /* generic setup */
+ ether_setup(dev);
+ dev->interrupt = 0;
+ dev->tbusy = 0;
+ dev->start = 0;
+
+ /* copy out MAC address */
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = readb(priv->macbase + (i << 1));
+
+ /* print config */
+ printk("%s: IRQ %d, memory %#lx-%#lx, "
+ "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n",
+ dev->name, priv->realirq, dev->mem_start, dev->mem_end - 1,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]);
+
+ /* reset board */
+
+ ResetBoard(dev);
+
+#ifdef MODULE
+ startslot = slot + 1;
+#endif


+
+ return 0;
+}
+

+/* ------------------------------------------------------------------------
+ * modularization support
+ * ------------------------------------------------------------------------ */
+
+#ifdef MODULE
+
+#define DEVMAX 5
+
+static char NameSpace[8 * DEVMAX];
+static struct device moddevs[DEVMAX] =
+ {{NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+ {NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+ {NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+ {NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+ {NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}};
+
+int irq=0;
+int io=0;
+
+int init_module(void)
+{
+ int z, res;
+
+ startslot = 0;
+ for (z = 0; z < DEVMAX; z++)
+ {
+ strcpy(moddevs[z].name, " ");
+ res = register_netdev(moddevs + z);
+ if (res != 0)
+ return (z > 0) ? 0 : -EIO;
+ }


+
+ return 0;
+}
+

+void cleanup_module(void)


+{
+ struct device *dev;

+ skmca_priv *priv;
+ int z;
+
+ if (MOD_IN_USE)
+ {
+ printk("cannot unload, module in use\n");
+ return;
+ }
+
+ for (z = 0; z < DEVMAX; z++)
+ {
+ dev = moddevs + z;
+ if (dev->priv != NULL)
+ {
+ priv = (skmca_priv*) dev->priv;
+ DeinitBoard(dev);
+ if (dev->irq != 0)
+ free_irq(dev->irq, dev);


+ dev->irq = 0;

+ unregister_netdev(dev);
+#if LINUX_VERSION_CODE >= 0x020200
+ mca_mark_as_unused(priv->slot);
+#endif
+ mca_set_adapter_procfn(priv->slot, NULL, NULL);
+ kfree_s(dev->priv, sizeof(skmca_priv));
+ dev->priv = NULL;
+ }
+ }
+}
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.5/linux/drivers/net/sk_mca.h linux/drivers/net/sk_mca.h
--- v2.3.5/linux/drivers/net/sk_mca.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sk_mca.h Mon Jun 7 14:34:46 1999
@@ -0,0 +1,174 @@
+#ifndef _SK_MCA_INCLUDE_
+#define _SK_MCA_INCLUDE_
+
+#ifdef _SK_MCA_DRIVER_
+
+/* Adapter ID's */
+#define SKNET_MCA_ID 0x6afd
+#define SKNET_JUNIOR_MCA_ID 0x6be9
+
+/* media enumeration - defined in a way that it fits onto the MC2+'s
+ POS registers... */
+
+typedef enum {Media_10Base2, Media_10BaseT,
+ Media_10Base5, Media_Unknown, Media_Count} skmca_medium;
+
+/* private structure */
+typedef struct
+ {
+ unsigned int slot; /* MCA-Slot-# */
+ unsigned int macbase; /* base address of MAC address PROM */
+ unsigned int ioregaddr; /* address of I/O-register (Lo) */
+ unsigned int ctrladdr; /* address of control/stat register */
+ unsigned int cmdaddr; /* address of I/O-command register */
+ int nextrx; /* index of next RX descriptor to
+ be read */
+ int nexttxput; /* index of next free TX descriptor */
+ int nexttxdone; /* index of next TX descriptor to
+ be finished */
+ int txbusy; /* # of busy TX descriptors */
+ struct enet_statistics stat; /* packet statistics */
+ int realirq; /* memorizes actual IRQ, even when
+ currently not allocated */
+ skmca_medium medium; /* physical cannector */
+ } skmca_priv;
+
+/* card registers: control/status register bits */
+
+#define CTRL_ADR_DATA 0 /* Bit 0 = 0 ->access data register */
+#define CTRL_ADR_RAP 1 /* Bit 0 = 1 ->access RAP register */
+#define CTRL_RW_WRITE 0 /* Bit 1 = 0 ->write register */
+#define CTRL_RW_READ 2 /* Bit 1 = 1 ->read register */
+#define CTRL_RESET_ON 0 /* Bit 3 = 0 ->reset board */
+#define CTRL_RESET_OFF 8 /* Bit 3 = 1 ->no reset of board */
+
+#define STAT_ADR_DATA 0 /* Bit 0 of ctrl register read back */
+#define STAT_ADR_RAP 1
+#define STAT_RW_WRITE 0 /* Bit 1 of ctrl register read back */
+#define STAT_RW_READ 2
+#define STAT_RESET_ON 0 /* Bit 3 of ctrl register read back */
+#define STAT_RESET_OFF 8
+#define STAT_IRQ_ACT 0 /* interrupt pending */
+#define STAT_IRQ_NOACT 16 /* no interrupt pending */
+#define STAT_IO_NOBUSY 0 /* no transfer busy */
+#define STAT_IO_BUSY 32 /* transfer busy */
+
+/* I/O command register bits */
+
+#define IOCMD_GO 128 /* Bit 7 = 1 -> start register xfer */
+
+/* LANCE registers */
+
+#define LANCE_CSR0 0 /* Status/Control */
+
+#define CSR0_ERR 0x8000 /* general error flag */
+#define CSR0_BABL 0x4000 /* transmitter timeout */
+#define CSR0_CERR 0x2000 /* collision error */
+#define CSR0_MISS 0x1000 /* lost Rx block */
+#define CSR0_MERR 0x0800 /* memory access error */
+#define CSR0_RINT 0x0400 /* receiver interrupt */
+#define CSR0_TINT 0x0200 /* transmitter interrupt */
+#define CSR0_IDON 0x0100 /* initialization done */
+#define CSR0_INTR 0x0080 /* general interrupt flag */
+#define CSR0_INEA 0x0040 /* interrupt enable */
+#define CSR0_RXON 0x0020 /* receiver enabled */
+#define CSR0_TXON 0x0010 /* transmitter enabled */
+#define CSR0_TDMD 0x0008 /* force transmission now */
+#define CSR0_STOP 0x0004 /* stop LANCE */
+#define CSR0_STRT 0x0002 /* start LANCE */
+#define CSR0_INIT 0x0001 /* read initialization block */
+
+#define LANCE_CSR1 1 /* addr bit 0..15 of initialization */
+#define LANCE_CSR2 2 /* 16..23 block */
+
+#define LANCE_CSR3 3 /* Bus control */
+#define CSR3_BCON_HOLD 0 /* Bit 0 = 0 -> BM1,BM0,HOLD */
+#define CSR3_BCON_BUSRQ 1 /* Bit 0 = 1 -> BUSAK0,BYTE,BUSRQ */
+#define CSR3_ALE_HIGH 0 /* Bit 1 = 0 -> ALE asserted high */
+#define CSR3_ALE_LOW 2 /* Bit 1 = 1 -> ALE asserted low */
+#define CSR3_BSWAP_OFF 0 /* Bit 2 = 0 -> no byte swap */
+#define CSR3_BSWAP_ON 0 /* Bit 2 = 1 -> byte swap */
+
+/* LANCE structures */
+
+typedef struct /* LANCE initialization block */
+ {
+ u16 Mode; /* mode flags */
+ u8 PAdr[6]; /* MAC address */
+ u8 LAdrF[8]; /* Multicast filter */
+ u32 RdrP; /* Receive descriptor */
+ u32 TdrP; /* Transmit descriptor */
+ } LANCE_InitBlock;
+
+/* Mode flags init block */
+
+#define LANCE_INIT_PROM 0x8000 /* enable promiscous mode */
+#define LANCE_INIT_INTL 0x0040 /* internal loopback */
+#define LANCE_INIT_DRTY 0x0020 /* disable retry */
+#define LANCE_INIT_COLL 0x0010 /* force collision */
+#define LANCE_INIT_DTCR 0x0008 /* disable transmit CRC */
+#define LANCE_INIT_LOOP 0x0004 /* loopback */
+#define LANCE_INIT_DTX 0x0002 /* disable transmitter */
+#define LANCE_INIT_DRX 0x0001 /* disable receiver */
+
+typedef struct /* LANCE Tx descriptor */
+ {
+ u16 LowAddr; /* bit 0..15 of address */
+ u16 Flags; /* bit 16..23 of address + Flags */
+ u16 Len; /* 2s complement of packet length */
+ u16 Status; /* Result of transmission */
+ } LANCE_TxDescr;
+
+#define TXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */
+#define TXDSCR_FLAGS_ERR 0x4000 /* summary error flag */
+#define TXDSCR_FLAGS_MORE 0x1000 /* more than one retry needed? */
+#define TXDSCR_FLAGS_ONE 0x0800 /* one retry? */
+#define TXDSCR_FLAGS_DEF 0x0400 /* transmission deferred? */
+#define TXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */
+#define TXDSCR_FLAGS_ENP 0x0100 /* last packet in chain? */
+
+#define TXDSCR_STATUS_BUFF 0x8000 /* buffer error? */
+#define TXDSCR_STATUS_UFLO 0x4000 /* silo underflow during transmit? */
+#define TXDSCR_STATUS_LCOL 0x1000 /* late collision? */
+#define TXDSCR_STATUS_LCAR 0x0800 /* loss of carrier? */
+#define TXDSCR_STATUS_RTRY 0x0400 /* retry error? */
+
+typedef struct /* LANCE Rx descriptor */
+ {
+ u16 LowAddr; /* bit 0..15 of address */
+ u16 Flags; /* bit 16..23 of address + Flags */
+ u16 MaxLen; /* 2s complement of buffer length */
+ u16 Len; /* packet length */
+ } LANCE_RxDescr;
+
+#define RXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */
+#define RXDSCR_FLAGS_ERR 0x4000 /* summary error flag */
+#define RXDSCR_FLAGS_FRAM 0x2000 /* framing error flag */
+#define RXDSCR_FLAGS_OFLO 0x1000 /* FIFO overflow? */
+#define RXDSCR_FLAGS_CRC 0x0800 /* CRC error? */
+#define RXDSCR_FLAGS_BUFF 0x0400 /* buffer error? */
+#define RXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */
+#define RXDCSR_FLAGS_ENP 0x0100 /* last packet in chain? */
+
+/* RAM layout */
+
+#define TXCOUNT 4 /* length of TX descriptor queue */
+#define LTXCOUNT 2 /* log2 of it */
+#define RXCOUNT 4 /* length of RX descriptor queue */
+#define LRXCOUNT 2 /* log2 of it */
+
+#define RAM_INITBASE 0 /* LANCE init block */
+#define RAM_TXBASE 24 /* Start of TX descriptor queue */
+#define RAM_RXBASE \
+(RAM_TXBASE + (TXCOUNT * 8)) /* Start of RX descriptor queue */
+#define RAM_DATABASE \
+(RAM_RXBASE + (RXCOUNT * 8)) /* Start of data area for frames */
+#define RAM_BUFSIZE 1580 /* max. frame size - should never be
+ reached */
+
+#endif /* _SK_MCA_DRIVER_ */
+
+extern int skmca_probe(struct device *);
+
+
+#endif /* _SK_MCA_INCLUDE_ */
\ No newline at end of file
diff -u --recursive --new-file v2.3.5/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.3.5/linux/drivers/pci/oldproc.c Fri May 14 18:55:20 1999
+++ linux/drivers/pci/oldproc.c Wed Jun 9 16:59:15 1999
@@ -102,6 +102,7 @@
X DEVICE( DEC, DEC_21150, "DC21150"),
X DEVICE( DEC, DEC_21152, "DC21152"),
X DEVICE( DEC, DEC_21153, "DC21153"),
+ DEVICE( DEC, DEC_21154, "DC21154"),
X DEVICE( CIRRUS, CIRRUS_7548, "GD 7548"),
X DEVICE( CIRRUS, CIRRUS_5430, "GD 5430"),
X DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"),
@@ -202,6 +203,8 @@
X DEVICE( MOTOROLA, MOTOROLA_MPC105,"MPC105 Eagle"),
X DEVICE( MOTOROLA, MOTOROLA_MPC106,"MPC106 Grackle"),
X DEVICE( MOTOROLA, MOTOROLA_RAVEN, "Raven"),
+ DEVICE( MOTOROLA, MOTOROLA_FALCON,"Falcon"),
+ DEVICE( MOTOROLA, MOTOROLA_CPX8216,"CPX8216"),
X DEVICE( PROMISE, PROMISE_20246, "IDE UltraDMA/33"),
X DEVICE( PROMISE, PROMISE_20262, "IDE UltraDMA/66"),
X DEVICE( PROMISE, PROMISE_5300, "DC5030"),
@@ -467,6 +470,7 @@
X DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"),
X DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128"),
X DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16"),
+ DEVICE( MOTOROLA_OOPS, MOTOROLA_FALCON,"Falcon"),
X DEVICE( SYMPHONY, SYMPHONY_101, "82C101"),
X DEVICE( TEKRAM, TEKRAM_DC290, "DC-290"),
X DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX"),
@@ -536,9 +540,11 @@
X DEVICE( INTEL, INTEL_82450GX, "82450GX Orion P6"),
X DEVICE( KTI, KTI_ET32P2, "ET32P2"),
X DEVICE( ADAPTEC, ADAPTEC_7810, "AIC-7810 RAID"),
+ DEVICE( ADAPTEC, ADAPTEC_7821, "AIC-7860"),
X DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"),
X DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855"),
X DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800"),
+ DEVICE( ADAPTEC, ADAPTEC_3860, "AIC-7860"),
X DEVICE( ADAPTEC, ADAPTEC_7860, "AIC-7860"),
X DEVICE( ADAPTEC, ADAPTEC_7861, "AIC-7861"),
X DEVICE( ADAPTEC, ADAPTEC_7870, "AIC-7870"),
@@ -552,13 +558,26 @@
X DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U"),
X DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U"),
X DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U"),
+ DEVICE( ADAPTEC, ADAPTEC_7885, "AIC-7885U"),
+ DEVICE( ADAPTEC, ADAPTEC_7886, "AIC-7886U"),
+ DEVICE( ADAPTEC, ADAPTEC_7887, "AIC-7887U"),
+ DEVICE( ADAPTEC, ADAPTEC_7888, "AIC-7888U"),
X DEVICE( ADAPTEC, ADAPTEC_1030, "ABA-1030 DVB receiver"),
X DEVICE( ADAPTEC2, ADAPTEC2_2940U2,"AHA-2940U2"),
- DEVICE( ADAPTEC2, ADAPTEC2_78902, "AIC-7890/1"),
+ DEVICE( ADAPTEC2, ADAPTEC2_2930U2,"AHA-2930U2"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7890B, "AIC-7890/1"),
X DEVICE( ADAPTEC2, ADAPTEC2_7890, "AIC-7890/1"),
X DEVICE( ADAPTEC2, ADAPTEC2_3940U2,"AHA-3940U2"),
X DEVICE( ADAPTEC2, ADAPTEC2_3950U2D,"AHA-3950U2D"),
X DEVICE( ADAPTEC2, ADAPTEC2_7896, "AIC-7896/7"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7892A, "AIC-7892"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7892B, "AIC-7892"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7892D, "AIC-7892"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7892P, "AIC-7892"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7899A, "AIC-7899"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7899B, "AIC-7899"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7899D, "AIC-7899"),
+ DEVICE( ADAPTEC2, ADAPTEC2_7899P, "AIC-7899"),
X DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL"),
X DEVICE( TIGERJET, TIGERJET_300, "Tiger300 ISDN"),
X DEVICE( ARK, ARK_STING, "Stingray"),
@@ -676,6 +695,8 @@
X case PCI_CLASS_SERIAL_USB: return "USB Controller";
X case PCI_CLASS_SERIAL_FIBER: return "Fiber Channel";
X
+ case PCI_CLASS_HOT_SWAP_CONTROLLER: return "Hot Swap Controller";
+
X default: return "Unknown class";
X }
X }
@@ -715,6 +736,7 @@
X case PCI_VENDOR_ID_OAK: return "OAK";
X case PCI_VENDOR_ID_WINBOND2: return "Winbond";
X case PCI_VENDOR_ID_MOTOROLA: return "Motorola";
+ case PCI_VENDOR_ID_MOTOROLA_OOPS: return "Motorola";
X case PCI_VENDOR_ID_PROMISE: return "Promise Technology";
X case PCI_VENDOR_ID_N9: return "Number Nine";
X case PCI_VENDOR_ID_UMC: return "UMC";
diff -u --recursive --new-file v2.3.5/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.3.5/linux/drivers/sbus/char/Config.in Mon May 31 22:28:06 1999
+++ linux/drivers/sbus/char/Config.in Wed Jun 9 14:44:25 1999
@@ -12,4 +12,10 @@
X tristate 'Bidirectional parallel port support (EXPERIMENTAL)' CONFIG_SUN_BPP
X tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX
X tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
+
+ # XXX Why don't we do "source drivers/char/Config.in" somewhere?
+ if [ "$CONFIG_PCI" = "y" ]; then
+ define_bool CONFIG_APM_RTC_IS_GMT y # no shit
+ bool 'PC-style RTC' CONFIG_RTC
+ fi
X fi
diff -u --recursive --new-file v2.3.5/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- v2.3.5/linux/drivers/sbus/char/aurora.c Mon May 31 22:28:06 1999
+++ linux/drivers/sbus/char/aurora.c Wed Jun 9 14:44:25 1999
@@ -53,6 +53,7 @@
X #include <linux/kernel.h>
X #include <linux/init.h>
X #include <linux/tqueue.h>
+#include <linux/delay.h>
X
X #include <asm/io.h>
X #include <asm/irq.h>
@@ -60,7 +61,6 @@
X #include <asm/system.h>
X #include <asm/segment.h>
X #include <asm/bitops.h>
-#include <asm/delay.h>
X #include <asm/kdebug.h>
X #include <asm/sbus.h>
X #include <asm/uaccess.h>
diff -u --recursive --new-file v2.3.5/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.3.5/linux/drivers/sbus/char/bpp.c Fri May 14 18:55:21 1999
+++ linux/drivers/sbus/char/bpp.c Wed Jun 9 14:44:25 1999
@@ -997,7 +997,7 @@
X instances[idx].enhanced = 0;
X instances[idx].direction = 0;
X instances[idx].mode = COMPATIBILITY;
- instances[idx].wait_queue = 0;
+ init_waitqueue_head(&instances[idx].wait_queue);
X instances[idx].run_length = 0;
X instances[idx].run_flag = 0;
X init_timer(&instances[idx].timer_list);
diff -u --recursive --new-file v2.3.5/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.5/linux/drivers/sbus/char/pcikbd.c Mon May 17 09:55:22 1999
+++ linux/drivers/sbus/char/pcikbd.c Wed Jun 9 14:44:25 1999
@@ -1,8 +1,8 @@
-/* $Id: pcikbd.c,v 1.29 1999/05/16 13:47:53 ecd Exp $
+/* $Id: pcikbd.c,v 1.30 1999/06/03 15:02:36 davem Exp $
X * pcikbd.c: Ultra/AX PC keyboard support.
X *


X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)

- * JavaStation(MrCoffee) support by Pete A. Zaitcev.
+ * JavaStation support by Pete A. Zaitcev.
X *
X * This code is mainly put together from various places in
X * drivers/char, please refer to these sources for credits
@@ -30,13 +30,16 @@
X #include <asm/io.h>
X #include <asm/uaccess.h>
X
-#ifdef __sparc_v9__
-#define PCI_KB_NAME "kb_ps2"
-#define PCI_MS_NAME "kdmouse"
-#else
-#define PCI_KB_NAME "keyboard"
-#define PCI_MS_NAME "mouse"
-#endif
+/*
+ * Different platforms provide different permutations of names.
+ * AXi - kb_ps2, kdmouse.
+ * MrCoffee - keyboard, mouse.
+ * Espresso - keyboard, kdmouse.
+ */
+#define PCI_KB_NAME1 "kb_ps2"
+#define PCI_KB_NAME2 "keyboard"
+#define PCI_MS_NAME1 "kdmouse"
+#define PCI_MS_NAME2 "mouse"
X
X #include "pcikbd.h"
X #include "sunserial.h"
@@ -502,7 +505,8 @@
X for_each_ebusdev(edev, ebus) {
X if(!strcmp(edev->prom_name, "8042")) {
X for_each_edevchild(edev, child) {
- if (!strcmp(child->prom_name, PCI_KB_NAME))
+ if (strcmp(child->prom_name, PCI_KB_NAME1) == 0 ||
+ strcmp(child->prom_name, PCI_KB_NAME2) == 0)
X goto found;
X }
X }
@@ -513,12 +517,14 @@
X
X found:
X pcikbd_iobase = child->base_address[0];
+#ifdef __sparc_v9__
X if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
X printk("8042: can't get region %lx, %d\n",
X pcikbd_iobase, (int)sizeof(unsigned long));
X return;
X }
X request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
+#endif
X
X pcikbd_irq = child->irqs[0];
X if (request_irq(pcikbd_irq, &pcikbd_interrupt,
@@ -548,7 +554,7 @@
X * XXX: my 3.1.3 PROM does not give me the beeper node for the audio
X * auxio register, though I know it is there... (ecd)
X *
- * Both JE1 & MrCoffe have no beeper. How about Krups? --zaitcev
+ * JavaStations appear not to have beeper. --zaitcev
X */
X if (!edev)
X pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
@@ -575,7 +581,6 @@
X }
X
X
-
X /*
X * Here begins the Mouse Driver.
X */
@@ -955,7 +960,8 @@
X for_each_ebusdev(edev, ebus) {
X if(!strcmp(edev->prom_name, "8042")) {
X for_each_edevchild(edev, child) {
- if (!strcmp(child->prom_name, PCI_MS_NAME))
+ if (strcmp(child->prom_name, PCI_MS_NAME1) == 0 ||
+ strcmp(child->prom_name, PCI_MS_NAME2) == 0)
X goto found;
X }
X }
@@ -1023,7 +1029,7 @@
X
X __initfunc(int ps2kbd_probe(unsigned long *memory_start))
X {
- int pnode, enode, node, dnode;
+ int pnode, enode, node, dnode, xnode;
X int kbnode = 0, msnode = 0, bnode = 0;
X int devices = 0;
X char prop[128];
@@ -1103,18 +1109,20 @@
X * For each '8042' on this EBus...
X */
X while (node) {
+ dnode = prom_getchild(node);
+
X /*
X * Does it match?
X */
- dnode = prom_getchild(node);
- dnode = prom_searchsiblings(dnode, PCI_KB_NAME);
- if (dnode == kbnode) {
+ if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME1)) == kbnode) {
+ ++devices;
+ } else if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME2)) == kbnode) {
X ++devices;
X }
X
- dnode = prom_getchild(node);
- dnode = prom_searchsiblings(dnode, PCI_MS_NAME);
- if (dnode == msnode) {
+ if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME1)) == msnode) {
+ ++devices;
+ } else if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME2)) == msnode) {
X ++devices;
X }
X
diff -u --recursive --new-file v2.3.5/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c
--- v2.3.5/linux/drivers/sbus/char/rtc.c Sun Oct 4 10:22:44 1998
+++ linux/drivers/sbus/char/rtc.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.13 1998/08/26 10:29:44 davem Exp $
+/* $Id: rtc.c,v 1.14 1999/06/03 15:02:38 davem Exp $
X *
X * Linux/SPARC Real Time Clock Driver
X * Copyright (C) 1996 Thomas K. Dyas (td...@eden.rutgers.edu)


@@ -107,6 +107,7 @@
X

X static int rtc_open(struct inode *inode, struct file *file)
X {
+
X if (rtc_busy)
X return -EBUSY;
X
@@ -144,14 +145,20 @@
X #ifdef MODULE
X int init_module(void)
X #else
-__initfunc(int rtc_init(void))
+__initfunc(int rtc_sun_init(void))
X #endif
X {
X int error;
X
+ if (mstk48t02_regs == 0) {
+ /* This diagnostic is a debugging aid... But a useful one. */
+ printk(KERN_ERR "rtc: no Mostek in this computer\n");


+ return -ENODEV;
+ }
+

X error = misc_register(&rtc_dev);
X if (error) {
- printk(KERN_ERR "rtc: unable to get misc minor\n");
+ printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n");
X return error;
X }
X
diff -u --recursive --new-file v2.3.5/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.3.5/linux/drivers/sbus/char/su.c Fri May 14 18:55:21 1999
+++ linux/drivers/sbus/char/su.c Wed Jun 9 14:44:25 1999
@@ -1,8 +1,8 @@
-/* $Id: su.c,v 1.19 1999/05/12 11:15:14 davem Exp $
+/* $Id: su.c,v 1.20 1999/06/03 15:02:40 davem Exp $
X * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
X *


X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)

- * Coypright (C) 1998 Pete Zaitcev (zai...@metabyte.com)
+ * Copyright (C) 1998-1999 Pete Zaitcev (zai...@metabyte.com)
X *
X * This is mainly a variation of drivers/char/serial.c,
X * credits go to authors mentioned therein.
@@ -92,6 +92,11 @@
X int su_serial_console_init(void);
X #endif
X
+enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
+static char *su_typev[] = { "???", "mouse", "kbd", "serial" };
+
+#define SU_PROPSIZE 128
+
X /*
X * serial.c saves memory when it allocates async_info upon first open.
X * We have parts of state structure together because we do call startup
@@ -107,8 +112,7 @@
X int line;
X int cflag;
X
- int kbd_node;
- int ms_node;
+ enum su_type port_type; /* Hookup type: e.g. mouse */
X int port_node;
X
X char name[16];
@@ -145,6 +149,18 @@
X unsigned long last_active; /* For async_struct, to be */
X };
X
+/*
+ * Scan status structure.
+ * "prop" is a local variable but it eats stack to keep it in each
+ * stack frame of a recursive procedure.
+ */
+struct su_probe_scan {
+ int msnode, kbnode; /* PROM nodes for mouse and keyboard */
+ int msx, kbx; /* minors for mouse and keyboard */
+ int devices; /* scan index */
+ char prop[SU_PROPSIZE];
+};
+
X static char *serial_name = "PCIO serial driver";
X static char serial_version[16];
X
@@ -223,8 +239,6 @@


X return 0;
X }
X

-#ifdef __sparc_v9__
-
X static inline
X unsigned int su_inb(struct su_struct *info, unsigned long offset)
X {
@@ -234,20 +248,7 @@
X static inline void
X su_outb(struct su_struct *info, unsigned long offset, int value)
X {
- outb(value, info->port + offset);
-}
-
-#else
-
-static inline
-unsigned int su_inb(struct su_struct *info, unsigned long offset)
-{
- return (unsigned int)(*(volatile unsigned char *)(info->port + offset));
-}
-
-static inline void
-su_outb(struct su_struct *info, unsigned long offset, int value)
-{
+#ifndef __sparc_v9__
X /*
X * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are
X * connected with a gate then go to SlavIO. When IRQ4 goes tristated
@@ -257,10 +258,9 @@
X * This problem is similar to what Alpha people suffer, see serial.c.
X */
X if (offset == UART_MCR) value |= UART_MCR_OUT2;
- *(volatile unsigned char *)(info->port + offset) = value;
-}
-
X #endif
+ outb(value, info->port + offset);
+}
X
X #define serial_in(info, off) su_inb(info, off)
X #define serial_inp(info, off) su_inb(info, off)
@@ -348,7 +348,7 @@
X
X do {
X ch = serial_inp(info, UART_RX);
- if (info->kbd_node) {
+ if (info->port_type == SU_PORT_KBD) {
X if(ch == SUNKBD_RESET) {
X l1a_state.kbd_id = 1;
X l1a_state.l1_down = 0;
@@ -529,7 +529,7 @@
X (status & UART_MSR_DCD))
X hardpps();
X #endif
- }
+ }
X if (status & UART_MSR_DCTS)
X icount->cts++;
X wake_up_interruptible(&info->delta_msr_wait);
@@ -775,7 +775,7 @@
X /*
X * Allocate the IRQ if necessary
X */
- if (info->kbd_node || info->ms_node) {
+ if (info->port_type != SU_PORT_PORT) {
X retval = request_irq(info->irq, su_kbd_ms_interrupt,
X SA_SHIRQ, info->name, info);
X } else {
@@ -956,7 +956,7 @@
X int bits;


X unsigned long flags;
X

- if (!info->kbd_node && !info->ms_node) {
+ if (info->port_type == SU_PORT_PORT) {
X if (!info->tty || !info->tty->termios)
X return;
X if (!info->port)
@@ -1133,9 +1133,9 @@
X struct su_struct *info = su_table;
X int lsr;
X
- if (!info->kbd_node)
+ if (!info->port_type != SU_PORT_KBD)
X ++info;
- if (!info)
+ if (!info->port_type != SU_PORT_KBD)
X return;
X
X do {
@@ -1151,9 +1151,9 @@
X {
X struct su_struct *info = su_table;
X
- if (!info->ms_node)
+ if (!info->port_type != SU_PORT_MS)
X ++info;
- if (!info)
+ if (!info->port_type != SU_PORT_MS)
X return;
X
X info->cflag &= ~(CBAUDEX | CBAUD);
@@ -2202,9 +2202,9 @@
X
X /*
X * ---------------------------------------------------------------------
- * su_init() and friends
+ * su_XXX_init() and friends
X *
- * su_init() is called at boot-time to initialize the serial driver.
+ * su_XXX_init() is called at boot-time to initialize the serial driver.
X * ---------------------------------------------------------------------
X */
X
@@ -2215,7 +2215,7 @@
X */
X __initfunc(static __inline__ void show_su_version(void))
X {
- char *revision = "$Revision: 1.19 $";
+ char *revision = "$Revision: 1.20 $";
X char *version, *p;
X
X version = strchr(revision, ' ');
@@ -2226,8 +2226,8 @@
X }
X
X /*
- * This routine is called by su_init() to initialize a specific serial
- * port. It determines what type of UART chip this serial port is
+ * This routine is called by su_{serial|kbd_ms}_init() to initialize a specific
+ * serial port. It determines what type of UART chip this serial port is
X * using: 8250, 16450, 16550, 16550A. The important question is
X * whether or not this UART is a 16550A, since this will determine
X * whether or not we can use its FIFO features.
@@ -2236,38 +2236,42 @@
X autoconfig(struct su_struct *info)
X {
X unsigned char status1, status2, scratch, scratch2;
-#ifdef __sparc_v9__
X struct linux_ebus_device *dev = 0;
X struct linux_ebus *ebus;
-#else
+#ifndef __sparc_v9__
X struct linux_prom_registers reg0;
X #endif


X unsigned long flags;
X

-#ifdef __sparc_v9__
+ if (!info->port_node || !info->port_type)


+ return;
+
+ /*

+ * First we look for Ebus-bases su's
+ */
X for_each_ebus(ebus) {
X for_each_ebusdev(dev, ebus) {
- if (!strncmp(dev->prom_name, "su", 2)) {
- if (dev->prom_node == info->kbd_node)
- goto ebus_done;
- if (dev->prom_node == info->ms_node)
- goto ebus_done;
+ if (dev->prom_node == info->port_node) {
+ info->port = dev->base_address[0];
+#ifdef __sparc_v9__
+ if (check_region(info->port, 8))
+ return;
+#endif
+ info->irq = dev->irqs[0];
+ goto ebus_done;
X }
X }
X }
-ebus_done:
- if (!dev)
- return;
-
- info->port = dev->base_address[0];
- if (check_region(info->port, 8))
- return;
X
- info->irq = dev->irqs[0];
+#ifdef __sparc_v9__
+ /*
+ * Not on Ebus, bailing.
+ */
+ return;
X #else
- if (!info->port_node)
- return;
-
+ /*
+ * Not on Ebus, must be OBIO.
+ */
X if (prom_getproperty(info->port_node, "reg",
X (char *)&reg0, sizeof(reg0)) == -1) {
X prom_printf("su: no \"reg\" property\n");
@@ -2279,21 +2283,24 @@
X prom_printf("su: cannot map\n");
X return;
X }
+
X /*
- * There is no intr property on MrCoffee, so hardwire it. Krups?
+ * There is no intr property on MrCoffee, so hardwire it.
X */
X info->irq = IRQ_4M(13);
X #endif
X
-#ifdef DEBUG_SERIAL_OPEN
- printk("Found 'su' at %016lx IRQ %s\n", dev->base_address[0],
- __irq_itoa(dev->irqs[0]));
+ebus_done:
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("Found 'su' at %016lx IRQ %s\n", info->port,
+ __irq_itoa(info->irq));
X #endif
X
X info->magic = SERIAL_MAGIC;
X
X save_flags(flags); cli();
-
+
X /*
X * Do a simple existence test first; if we fail this, there's
X * no point trying anything else.
@@ -2312,17 +2319,20 @@
X return; /* We failed; there's nothing here */
X }
X
-#if 0 /* P3: This does not work on MrCoffee. OUT2 is 0x80 - should work... */
X scratch = serial_inp(info, UART_MCR);
X serial_outp(info, UART_MCR, UART_MCR_LOOP | scratch);
X serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
X status1 = serial_inp(info, UART_MSR) & 0xF0;
X serial_outp(info, UART_MCR, scratch);
X if (status1 != 0x90) {
+ /*
+ * This code fragment used to fail, now it fixed itself.
+ * We keep the printout for a case.
+ */
+ printk("su: loopback returned status 0x%02x\n", status1);
X restore_flags(flags);
X return;
X }
-#endif
X
X scratch2 = serial_in(info, UART_LCR);
X serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */
@@ -2389,10 +2399,7 @@
X return;
X }
X
- if (info->kbd_node || info->ms_node)
- sprintf(info->name, "su(%s)", info->ms_node ? "mouse" : "kbd");
- else
- strcpy(info->name, "su(serial)");
+ sprintf(info->name, "su(%s)", su_typev[info->port_type]);
X
X #ifdef __sparc_v9__
X request_region(info->port, 8, info->name);
@@ -2494,13 +2501,16 @@
X info->tqueue.routine = do_softint;
X info->tqueue.data = info;
X info->cflag = serial_driver.init_termios.c_cflag;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
X
X autoconfig(info);
X if (info->type == PORT_UNKNOWN)
X continue;
X
- printk(KERN_INFO "%s at %16lx (irq = %s) is a %s\n",
- info->name, info->port, __irq_itoa(info->irq),
+ printk(KERN_INFO "%s at 0x%lx (tty %d irq %s) is a %s\n",
+ info->name, (long)info->port, i, __irq_itoa(info->irq),
X uart_config[info->type].name);
X }
X
@@ -2519,11 +2529,15 @@
X info->type = PORT_UNKNOWN;
X info->baud_base = BAUD_BASE;
X
- if (info->kbd_node)
+ if (info->port_type == SU_PORT_KBD)
X info->cflag = B1200 | CS8 | CLOCAL | CREAD;
X else
X info->cflag = B4800 | CS8 | CLOCAL | CREAD;
X
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+
X autoconfig(info);
X if (info->type == PORT_UNKNOWN)
X continue;
@@ -2533,7 +2547,7 @@
X uart_config[info->type].name);
X
X startup(info);
- if (info->kbd_node)
+ if (info->port_type == SU_PORT_KBD)
X keyboard_zsinit(su_put_char_kbd);
X else
X sun_mouse_zsinit();
@@ -2541,154 +2555,126 @@


X return 0;
X }
X

-__initfunc(int su_probe (unsigned long *memory_start))
+/*
+ * We got several platforms which present 'su' in different parts
+ * of device tree. 'su' may be found under obio, ebus, isa and pci.
+ * We walk over the tree and find them wherever PROM hides them.
+ */
+__initfunc(void su_probe_any(struct su_probe_scan *t, int sunode))
X {
- struct su_struct *info = su_table;


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

echo 'End of part 11'
echo 'File patch-2.3.6 is continued in part 12'
echo 12 > _shar_seq_.tmp
exit 0

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part13

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


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

X p->needsdtr_copy |= (1<<tindex);
X
- if (p->flags & AHC_SEEPROM_FOUND)
+ p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
+ p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
+ if (p->transinfo[tindex].user_offset)
X {
- p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
- p->transinfo[tindex].goal_offset = p->transinfo[tindex].user_offset;
- }
- else
- {
- if (p->features & AHC_ULTRA2)
- {
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
- }
- else if (p->features & AHC_ULTRA)
- {
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
- }
- else
- {
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
- }
X if (p->features & AHC_ULTRA2)
X p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
X else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
@@ -2952,14 +2931,57 @@
X p->needsdtr_copy &= ~(1<<tindex);
X p->transinfo[tindex].goal_period = 0;
X p->transinfo[tindex].goal_offset = 0;
+ p->transinfo[tindex].goal_options = 0;
+ }
+ if ( (buffer[2] & SCSI_VERSION_BITS) == 3 )
+ {
+ p->dev_flags[tindex] |= DEVICE_SCSI_3;
+ /*
+ * OK, we are a SCSI 3 device and we are in need of negotiation.
+ * Use PPR messages instead of WDTR and SDTR messages.
+ */
+ if ( (p->needsdtr & (1<<tindex)) ||
+ (p->needwdtr & (1<<tindex)) )
+ {
+ p->needppr |= (1<<tindex);
+ p->needppr_copy |= (1<<tindex);
+ }
+ p->needwdtr &= ~(1<<tindex);
+ p->needwdtr_copy &= ~(1<<tindex);
+ p->needsdtr &= ~(1<<tindex);
+ p->needsdtr_copy &= ~(1<<tindex);
+ }
+ /*
+ * Get the INQUIRY checksum. We use this on Ultra 160/m
+ * and older devices both. It allows us to drop speed on any bus type
+ * while at the same time giving us the needed domain validation for
+ * Ultra 160/m
+ *
+ * Note: We only get the checksum and set the SCANNED bit if this is
+ * one of our dtr commands. If we don't do this, then we end up
+ * getting bad checksum results on the mid-level SCSI code's INQUIRY
+ * commands.
+ */
+ if(p->dev_dtr_cmnd[tindex] == cmd) {
+ unsigned int checksum = 0;
+ int *ibuffer;
+ int i=0;
+
+ ibuffer = (int *)buffer;
+ for( i = 0; i < (cmd->request_bufflen >> 2); i++)
+ {
+ checksum += ibuffer[i];
+ }
+ p->dev_checksum[tindex] = checksum;
+ p->dev_flags[tindex] |= DEVICE_SCANNED;
+ p->dev_flags[tindex] |= DEVICE_PRINT_DTR;
X }
- p->dev_flags[tindex] |= DEVICE_SCANNED;
- p->dev_flags[tindex] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR;
X #undef WIDE_INQUIRY_BITS
X #undef SYNC_INQUIRY_BITS
+#undef SCSI_VERSION_BITS
X }
X }
- else if ((scb->flags & (SCB_MSGOUT_WDTR | SCB_MSGOUT_SDTR)) != 0)
+ else if ((scb->flags & SCB_MSGOUT_BITS) != 0)
X {
X unsigned short mask;
X int message_error = FALSE;
@@ -2979,11 +3001,11 @@
X
X if (scb->flags & SCB_MSGOUT_WDTR)
X {
- p->wdtr_pending &= ~mask;
+ p->dtr_pending &= ~mask;
X if (message_error)
X {
X if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
- (p->dev_flags[tindex] & DEVICE_PRINT_WDTR) )
+ (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
X {
X printk(INFO_LEAD "Device failed to complete Wide Negotiation "
X "processing and\n", p->host_no, CTL_OF_SCB(scb));
@@ -2991,7 +3013,6 @@
X "disabling future\n", p->host_no, CTL_OF_SCB(scb));
X printk(INFO_LEAD "Wide negotiation to this device.\n", p->host_no,
X CTL_OF_SCB(scb));
- p->dev_flags[tindex] &= ~DEVICE_PRINT_WDTR;
X }
X p->needwdtr &= ~mask;
X p->needwdtr_copy &= ~mask;
@@ -2999,11 +3020,11 @@
X }
X if (scb->flags & SCB_MSGOUT_SDTR)
X {
- p->sdtr_pending &= ~mask;
+ p->dtr_pending &= ~mask;
X if (message_error)
X {
X if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
- (p->dev_flags[tindex] & DEVICE_PRINT_SDTR) )
+ (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
X {
X printk(INFO_LEAD "Device failed to complete Sync Negotiation "
X "processing and\n", p->host_no, CTL_OF_SCB(scb));
@@ -3011,12 +3032,38 @@
X "disabling future\n", p->host_no, CTL_OF_SCB(scb));
X printk(INFO_LEAD "Sync negotiation to this device.\n", p->host_no,
X CTL_OF_SCB(scb));
- p->dev_flags[tindex] &= ~DEVICE_PRINT_SDTR;
+ p->dev_flags[tindex] &= ~DEVICE_PRINT_DTR;
X }
X p->needsdtr &= ~mask;
X p->needsdtr_copy &= ~mask;
X }
X }
+ if (scb->flags & SCB_MSGOUT_PPR)
+ {
+ p->dtr_pending &= ~mask;
+ if(message_error)
+ {
+ if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+ (p->dev_flags[tindex] & DEVICE_PRINT_DTR) )
+ {
+ printk(INFO_LEAD "Device failed to complete Parallel Protocol "
+ "Request processing and\n", p->host_no, CTL_OF_SCB(scb));
+ printk(INFO_LEAD "returned a sense error code for invalid message, "
+ "disabling future\n", p->host_no, CTL_OF_SCB(scb));
+ printk(INFO_LEAD "Parallel Protocol Request negotiation to this "
+ "device.\n", p->host_no, CTL_OF_SCB(scb));
+ }
+ /*
+ * Disable PPR negotiation and revert back to WDTR and SDTR setup
+ */
+ p->needppr &= ~mask;
+ p->needppr_copy &= ~mask;
+ p->needsdtr |= mask;
+ p->needsdtr_copy |= mask;
+ p->needwdtr |= mask;
+ p->needwdtr_copy |= mask;
+ }
+ }
X }
X queue_depth = p->dev_temp_queue_depth[tindex];
X if (queue_depth >= p->dev_active_cmds[tindex])
@@ -3058,16 +3105,6 @@
X p->dev_active_cmds[tindex]--;
X p->activescbs--;
X
- /*
- * If this was an untagged I/O, unbusy the target so the sequencer won't
- * mistake things later
- */
- if (aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun, FALSE) ==
- scb->hscb->tag)
- {
- aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun, TRUE);
- }
-
X {
X int actual;
X
@@ -3122,7 +3159,7 @@
X #endif /* AIC7XXX_PROC_STATS */
X }
X #ifdef AIC7XXX_PROC_STATS
- x = -10;
+ x = -11;
X while(actual)
X {
X actual >>= 1;
@@ -3429,11 +3466,10 @@
X if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
X printk(INFO_LEAD "Cleaning up status information "
X "and delayed_scbs.\n", p->host_no, channel, i, lun);
- p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
+ p->dev_flags[i] &= ~(BUS_DEVICE_RESET_PENDING | DEVICE_PARITY_ERROR);
X if ( tag == SCB_LIST_NULL )
X {
- p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR |
- DEVICE_RESET_DELAY;
+ p->dev_flags[i] |= DEVICE_PRINT_DTR | DEVICE_RESET_DELAY;
X p->dev_expires[i] = jiffies + (4 * HZ);
X p->dev_timer_active |= (0x01 << i);
X p->dev_last_queue_full_count[i] = 0;
@@ -3625,7 +3661,7 @@
X if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
X printk(INFO_LEAD "Cleaning disconnected scbs "
X "list.\n", p->host_no, channel, target, lun);
- if (p->features & AHC_PAGESCBS)
+ if (p->flags & AHC_PAGESCBS)
X {
X unsigned char next, prev, scb_index;
X
@@ -3641,14 +3677,14 @@
X printk(WARN_LEAD "Disconnected List inconsistency; SCB index=%d, "
X "numscbs=%d\n", p->host_no, channel, target, lun, scb_index,
X p->scb_data->numscbs);
- next = aic7xxx_rem_scb_from_disc_list(p, next);
+ next = aic7xxx_rem_scb_from_disc_list(p, next, prev);
X }
X else
X {
X scbp = p->scb_data->scb_array[scb_index];
X if (aic7xxx_match_scb(p, scbp, target, channel, lun, tag))
X {
- next = aic7xxx_rem_scb_from_disc_list(p, next);
+ next = aic7xxx_rem_scb_from_disc_list(p, next, prev);
X if (scbp->flags & SCB_WAITINGQ)
X {
X p->dev_active_cmds[TARGET_INDEX(scbp->cmd)]++;
@@ -3677,7 +3713,7 @@
X * Walk the free list making sure no entries on the free list have
X * a valid SCB_TAG value or SCB_CONTROL byte.
X */
- if (p->features & AHC_PAGESCBS)
+ if (p->flags & AHC_PAGESCBS)
X {
X unsigned char next;
X
@@ -3734,7 +3770,6 @@
X {
X aic_outb(p, SCB_LIST_NULL, SCB_TAG);
X aic_outb(p, SCB_LIST_NULL, SCB_NEXT);
- aic_outb(p, SCB_LIST_NULL, SCB_PREV);
X aic_outb(p, 0, SCB_CONTROL);
X aic7xxx_add_curscb_to_free_list(p);
X }
@@ -3863,28 +3898,35 @@
X if (channel == 1)
X {
X p->needsdtr |= (p->needsdtr_copy & 0xFF00);
- p->sdtr_pending &= 0x00FF;
+ p->dtr_pending &= 0x00FF;
X offset_min = 8;
X offset_max = 16;
X }
X else
X {
- if (p->features & AHC_WIDE)
+ if (p->features & AHC_TWIN)
X {
- p->needsdtr = p->needsdtr_copy;
- p->needwdtr = p->needwdtr_copy;
- p->sdtr_pending = 0x0;
- p->wdtr_pending = 0x0;
+ /* Channel A */
+ p->needsdtr |= (p->needsdtr_copy & 0x00FF);
+ p->dtr_pending &= 0xFF00;
X offset_min = 0;
- offset_max = 16;
+ offset_max = 8;
X }
X else
X {
- /* Channel A */
- p->needsdtr |= (p->needsdtr_copy & 0x00FF);
- p->sdtr_pending &= 0xFF00;
+ p->needppr = p->needppr_copy;
+ p->needsdtr = p->needsdtr_copy;
+ p->needwdtr = p->needwdtr_copy;
+ p->dtr_pending = 0x0;
X offset_min = 0;
- offset_max = 8;
+ if (p->features & AHC_WIDE)
+ {
+ offset_max = 16;
+ }
+ else
+ {
+ offset_max = 8;
+ }
X }
X }
X
@@ -4188,6 +4230,30 @@
X
X /*+F*************************************************************************
X * Function:
+ * aic7xxx_construct_ppr
+ *
+ * Description:
+ * Build up a Parallel Protocol Request message for use with SCSI-3
+ * devices.
+ *-F*************************************************************************/
+static void
+aic7xxx_construct_ppr(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
+{
+ int tindex = TARGET_INDEX(scb->cmd);
+
+ p->msg_buf[p->msg_index++] = MSG_EXTENDED;
+ p->msg_buf[p->msg_index++] = MSG_EXT_PPR_LEN;
+ p->msg_buf[p->msg_index++] = MSG_EXT_PPR;
+ p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_period;
+ p->msg_buf[p->msg_index++] = 0;
+ p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_offset;
+ p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_width;
+ p->msg_buf[p->msg_index++] = p->transinfo[tindex].goal_options;
+ p->msg_len += 8;
+}
+
+/*+F*************************************************************************
+ * Function:
X * aic7xxx_construct_sdtr
X *
X * Description:
@@ -4304,10 +4370,10 @@
X /*
X * Go back to async/narrow transfers and renegotiate.
X */
+ p->needppr |= (p->needppr_copy & targ_mask);
X p->needsdtr |= (p->needsdtr_copy & targ_mask);
X p->needwdtr |= (p->needwdtr_copy & targ_mask);
- p->sdtr_pending &= ~targ_mask;
- p->wdtr_pending &= ~targ_mask;
+ p->dtr_pending &= ~targ_mask;
X aic_outb(p, 0, TARG_SCSIRATE + tindex);
X if (p->features & AHC_ULTRA2)
X aic_outb(p, 0, TARG_OFFSET + tindex);
@@ -4315,7 +4381,7 @@
X if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
X printk(INFO_LEAD "Bus Device Reset delivered.\n", p->host_no, channel,
X target, -1);
- aic7xxx_run_done_queue(p, /*complete*/ FALSE);
+ aic7xxx_run_done_queue(p, /*complete*/ TRUE);
X }
X
X /*+F*************************************************************************
@@ -4360,6 +4426,8 @@
X p->host_no, channel, target, lun,
X aic_inb(p, SAVED_TCL), aic_inb(p, ARG_1),
X (aic_inb(p, SEQADDR1) << 8) | aic_inb(p, SEQADDR0));
+ if (aic7xxx_panic_on_abort)
+ aic7xxx_panic_abort(p, NULL);
X }
X break;
X
@@ -4387,7 +4455,7 @@
X lun, aic_inb(p, LASTPHASE), aic_inb(p, SAVED_TCL));
X
X aic7xxx_reset_channel(p, channel, /*initiate reset*/ TRUE);
- aic7xxx_run_done_queue(p, FALSE);
+ aic7xxx_run_done_queue(p, TRUE);
X
X }
X break;
@@ -4517,7 +4585,7 @@
X aic7xxx_reset_device(p, target, channel, lun, i);
X reset++;
X }
- aic7xxx_run_done_queue(p, FALSE);
+ aic7xxx_run_done_queue(p, TRUE);
X }
X }
X aic7xxx_verbose = old_verbose;
@@ -4533,6 +4601,51 @@
X aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
X }
X }
+ else if (scb->flags & SCB_MSGOUT_PPR)
+ {
+ /*
+ * As per the draft specs, any device capable of supporting any of
+ * the option values other than 0 are not allowed to reject the
+ * PPR message. Instead, they must negotiate out what they do
+ * support instead of rejecting our offering.
+ */
+ p->needppr &= ~target_mask;
+ p->needppr_copy &= ~target_mask;
+ aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT,
+ (AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE));
+ aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
+ p->transinfo[tindex].goal_options = 0;
+ p->dtr_pending &= ~target_mask;
+ scb->flags &= ~SCB_MSGOUT_BITS;
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Device is rejecting PPR messages, falling "
+ "back.\n", p->host_no, channel, target, lun);
+ }
+ if ( p->transinfo[tindex].goal_width )
+ {
+ p->needwdtr |= target_mask;
+ p->needwdtr_copy |= target_mask;
+ p->dtr_pending |= target_mask;
+ scb->flags |= SCB_MSGOUT_WDTR;
+ }
+ if ( p->transinfo[tindex].goal_offset )
+ {
+ p->needsdtr |= target_mask;
+ p->needsdtr_copy |= target_mask;
+ if( !(p->dtr_pending & target_mask) )
+ {
+ p->dtr_pending |= target_mask;
+ scb->flags |= SCB_MSGOUT_SDTR;
+ }
+ }
+ if ( p->dtr_pending & target_mask )
+ {
+ aic_outb(p, HOST_MSG, MSG_OUT);
+ aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
+ }
+ }
X else if (scb->flags & SCB_MSGOUT_WDTR)
X {
X /*
@@ -4540,20 +4653,18 @@
X */
X p->needwdtr &= ~target_mask;
X p->needwdtr_copy &= ~target_mask;
- p->wdtr_pending &= ~target_mask;
+ p->dtr_pending &= ~target_mask;
X scb->flags &= ~SCB_MSGOUT_BITS;
X aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT,
X (AHC_TRANS_ACTIVE|AHC_TRANS_GOAL|AHC_TRANS_CUR));
- aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0,
+ aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
X AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
- if ( (p->needsdtr_copy & target_mask) &&
- !(p->sdtr_pending & target_mask) )
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
X {
- p->sdtr_pending |= target_mask;
- scb->flags |= SCB_MSGOUT_SDTR;
- aic_outb(p, HOST_MSG, MSG_OUT);
- aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+ printk(INFO_LEAD "Device is rejecting WDTR messages, using "
+ "narrow transfers.\n", p->host_no, channel, target, lun);
X }
+ p->needsdtr |= (p->needsdtr_copy & target_mask);
X }
X else if (scb->flags & SCB_MSGOUT_SDTR)
X {
@@ -4562,10 +4673,15 @@
X */
X p->needsdtr &= ~target_mask;
X p->needsdtr_copy &= ~target_mask;
- p->sdtr_pending &= ~target_mask;
+ p->dtr_pending &= ~target_mask;
X scb->flags &= ~SCB_MSGOUT_SDTR;
- aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0,
+ aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
X (AHC_TRANS_CUR|AHC_TRANS_ACTIVE|AHC_TRANS_GOAL));
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Device is rejecting SDTR messages, using "
+ "async transfers.\n", p->host_no, channel, target, lun);
+ }
X }
X else if (aic7xxx_verbose & VERBOSE_SEQINT)
X {
@@ -4681,41 +4797,24 @@
X * However, if this SCB already was attempting to negotiate,
X * then we assume this isn't the problem and skip this part.
X */
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
X if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
X (p->dev_flags[tindex] & DEVICE_SCANNED) &&
- !(p->wdtr_pending & target_mask) &&
- !(p->sdtr_pending & target_mask) )
+ !(p->dtr_pending & target_mask) )
X {
+ p->needppr |= (p->needppr_copy & target_mask);
X p->needwdtr |= (p->needwdtr_copy & target_mask);
X p->needsdtr |= (p->needsdtr_copy & target_mask);
X }
- else if ( (scb->cmd == p->dev_wdtr_cmnd[tindex]) ||
- (scb->cmd == p->dev_sdtr_cmnd[tindex]) )
+ else if ( scb->cmd == p->dev_dtr_cmnd[tindex] )
X {
X /*
X * This is already a negotiation command, so we must have
- * already done either WDTR or SDTR (or maybe both). So
- * we simply check sdtr_pending and needsdtr to see if we
- * should throw out SDTR on this command.
- *
- * Note: Don't check the needsdtr_copy here, instead just
- * check to see if WDTR wiped out our SDTR and set needsdtr.
- * Even if WDTR did wipe out SDTR and set needsdtr, if
- * parse_msg() then turned around and started our SDTR
- * in back to back fasion, then conclusion of that should
- * have negated any needsdtr setting. That's why we only
- * check needsdtr and sdtr_pending.
+ * already done PPR, WDTR or SDTR. Since our negotiation
+ * could have gotten rejected, we don't really know the
+ * full state of things. Don't do anything here, and allow
+ * the negotiation_complete() handler to do the right
+ * thing.
X */
- scb->flags &= ~SCB_MSGOUT_BITS;
- if ( (scb->cmd == p->dev_wdtr_cmnd[tindex]) &&
- !(p->sdtr_pending & target_mask) &&
- (p->needsdtr & target_mask) )
- {
- p->sdtr_pending |= target_mask;
- hscb->control |= MK_MESSAGE;
- scb->flags |= SCB_MSGOUT_SDTR;
- }
X
X /*
X * This is the important part though. We are getting sense
@@ -4736,43 +4835,13 @@
X hscb->data_pointer = scb->sg_list[0].address;
X }
X }
-#else
- if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
- !(scb->flags & SCB_MSGOUT_BITS) &&
- (scb->cmd->lun == 0) &&
- (p->dev_flags[TARGET_INDEX(scb->cmd)] & DEVICE_SCANNED) )
- {
- if ( (p->needwdtr_copy & target_mask) &&
- !(p->wdtr_pending & target_mask) &&
- !(p->sdtr_pending & target_mask) )
- {
- p->needwdtr |= target_mask;
- p->wdtr_pending |= target_mask;
- hscb->control |= MK_MESSAGE;
- scb->flags |= SCB_MSGOUT_WDTR;
- }
- if ( p->needsdtr_copy & target_mask )
- {
- p->needsdtr |= target_mask;
- if ( !(p->wdtr_pending & target_mask) &&
- !(p->sdtr_pending & target_mask) )
- {
- p->sdtr_pending |= target_mask;
- hscb->control |= MK_MESSAGE;
- scb->flags |= SCB_MSGOUT_SDTR;
- }
- }
- }
- else
- scb->flags &= ~SCB_MSGOUT_BITS;
-#endif /* AIC7XXX_FAKE_NEGOTIATION_CMDS */
X scb->flags |= SCB_SENSE;
X /*
X * Ensure the target is busy since this will be an
X * an untagged request.
X */
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
X {
X if (scb->flags & SCB_MSGOUT_BITS)
X printk(INFO_LEAD "Requesting SENSE with %s\n", p->host_no,
@@ -4914,7 +4983,8 @@
X }
X }
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose & VERBOSE_MINOR_ERROR)
+ if( (aic7xxx_verbose & VERBOSE_MINOR_ERROR) ||
+ (aic7xxx_verbose > 0xffff) )
X {
X if (queue_flag)
X printk(INFO_LEAD "Queue full received; queue depth %d, "
@@ -4928,8 +4998,6 @@
X #endif
X if (queue_flag)
X {
- p->dev_temp_queue_depth[tindex] =
- p->dev_active_cmds[tindex];
X if ( p->dev_last_queue_full[tindex] !=
X p->dev_active_cmds[tindex] )
X {
@@ -4951,10 +5019,28 @@
X p->dev_active_cmds[tindex];
X p->dev_last_queue_full[tindex] = 0;
X p->dev_last_queue_full_count[tindex] = 0;
+ p->dev_temp_queue_depth[tindex] =
+ p->dev_active_cmds[tindex];
+ }
+ else if (p->dev_active_cmds[tindex] == 0)
+ {
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION)
+ {
+ printk(INFO_LEAD "QUEUE_FULL status received with 0 "
+ "commands active.\n", p->host_no, CTL_OF_SCB(scb));
+ printk(INFO_LEAD "Tagged Command Queueing disabled\n",
+ p->host_no, CTL_OF_SCB(scb));
+ }
+ p->dev_max_queue_depth[tindex] = 1;
+ p->dev_temp_queue_depth[tindex] = 1;
+ scb->tag_action = 0;
+ scb->hscb->control &= ~(MSG_ORDERED_Q_TAG|MSG_SIMPLE_Q_TAG);
X }
X else
X {
X p->dev_flags[tindex] |= DEVICE_WAS_BUSY;
+ p->dev_temp_queue_depth[tindex] =
+ p->dev_active_cmds[tindex];
X }
X }
X break;
@@ -4989,7 +5075,7 @@
X */
X
X if ( !(scb->flags & SCB_DEVICE_RESET) &&
- (aic_inb(p, MSG_OUT) == MSG_IDENTIFYFLAG) &&
+ (msg_out == MSG_IDENTIFYFLAG) &&
X (scb->hscb->control & TAG_ENB) )
X {
X p->msg_buf[p->msg_index++] = scb->tag_action;
@@ -5020,34 +5106,68 @@
X printk(INFO_LEAD "Abort message mailed.\n", p->host_no,
X CTL_OF_SCB(scb));
X }
- else if (scb->flags & SCB_MSGOUT_WDTR)
+ else if (scb->flags & SCB_MSGOUT_PPR)
X {
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
+ unsigned int max_sync, period;
+ unsigned char options = p->transinfo[tindex].goal_options;
+
+ if (p->features & AHC_ULTRA2)
+ {
+ if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
+ !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
+ {
+ if( (p->features & AHC_ULTRA3) &&
+ (p->dev_flags[tindex] & DEVICE_SCSI_3) &&
+ (p->transinfo[tindex].goal_width ==
+ MSG_EXT_WDTR_BUS_16_BIT) &&
+ (options != 0) )
+ {
+ max_sync = AHC_SYNCRATE_ULTRA3;
+ }
+ else
+ {
+ max_sync = AHC_SYNCRATE_ULTRA2;
+ }
+ }
+ else
+ {
+ max_sync = AHC_SYNCRATE_ULTRA;
+ }
+ }
+ else if (p->features & AHC_ULTRA)
+ {
+ max_sync = AHC_SYNCRATE_ULTRA;
+ }
+ else
+ {
+ max_sync = AHC_SYNCRATE_FAST;
+ }
+ period = p->transinfo[tindex].goal_period;
+ aic7xxx_find_syncrate(p, &period, max_sync, &options);
+ p->transinfo[tindex].goal_period = period;
+ p->transinfo[tindex].goal_options = options;
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Sending PPR (%d/%d/%d/%d) message.\n",
+ p->host_no, CTL_OF_SCB(scb), period,
+ p->transinfo[tindex].goal_offset,
+ p->transinfo[tindex].goal_width, options);
+ }
+ aic7xxx_construct_ppr(p, scb);
+ }
+ else if (scb->flags & SCB_MSGOUT_WDTR)
+ {
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
X printk(INFO_LEAD "Sending WDTR message.\n", p->host_no,
X CTL_OF_SCB(scb));
-#endif
- aic7xxx_construct_wdtr(p,
- p->transinfo[TARGET_INDEX(scb->cmd)].goal_width);
+ }
+ aic7xxx_construct_wdtr(p, p->transinfo[tindex].goal_width);
X }
X else if (scb->flags & SCB_MSGOUT_SDTR)
X {
X unsigned int max_sync, period;
- /*
- * We need to set an accurate goal_offset instead of
- * the ridiculously high one we default to. We should
- * now know if we are wide. Plus, the WDTR code will
- * set our goal_offset for us as well.
- */
- if (p->transinfo[tindex].goal_offset)
- {
- if (p->features & AHC_ULTRA2)
- p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
- else if (p->transinfo[tindex].cur_width == MSG_EXT_WDTR_BUS_16_BIT)
- p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
- else
- p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
- }
+ unsigned char options = 0;
X /*
X * Now that the device is selected, use the bits in SBLKCTL and
X * SSTAT2 to determine the max sync rate for this device.
@@ -5073,14 +5193,14 @@
X max_sync = AHC_SYNCRATE_FAST;
X }
X period = p->transinfo[tindex].goal_period;
- aic7xxx_find_syncrate(p, &period, max_sync);
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
+ aic7xxx_find_syncrate(p, &period, max_sync, &options);
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
X printk(INFO_LEAD "Sending SDTR %d/%d message.\n", p->host_no,
X CTL_OF_SCB(scb),
X p->transinfo[tindex].goal_period,
X p->transinfo[tindex].goal_offset);
-#endif
+ }
X aic7xxx_construct_sdtr(p, period,
X p->transinfo[tindex].goal_offset);
X }
@@ -5154,15 +5274,15 @@
X #if AIC7XXX_NOT_YET
X case TRACEPOINT:
X {
- printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no, channel,
- target, lun);
+ printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no,
+ channel, target, lun);
X }
X break;
X
X case TRACEPOINT2:
X {
- printk(INFO_LEAD "Tracepoint #2 reached.\n", p->host_no, channel,
- target, lun);
+ printk(INFO_LEAD "Tracepoint #2 reached.\n", p->host_no,
+ channel, target, lun);
X }
X break;
X
@@ -5237,7 +5357,7 @@
X case MSG_EXT_SDTR:
X {
X unsigned int period, offset;
- unsigned char maxsync, saved_offset;
+ unsigned char maxsync, saved_offset, options;
X struct aic7xxx_syncrate *syncrate;
X
X if (p->msg_buf[1] != MSG_EXT_SDTR_LEN)
@@ -5253,7 +5373,13 @@
X
X period = p->msg_buf[3];
X saved_offset = offset = p->msg_buf[4];
+ options = 0;
X
+ /*
+ * Even if we are an Ultra3 card, don't allow Ultra3 sync rates when
+ * using the SDTR messages. We need the PPR messages to enable the
+ * higher speeds that include things like Dual Edge clocking.
+ */
X if (p->features & AHC_ULTRA2)
X {
X if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
@@ -5283,7 +5409,9 @@
X if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
X (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) )
X {
- if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+ if (!(p->dev_flags[tindex] & DEVICE_SCANNED) &&
+ !(p->needsdtr_copy & target_mask) &&
+ (p->transinfo[tindex].user_offset) )
X {
X /*
X * Not only is the device starting this up, but it also hasn't
@@ -5295,38 +5423,49 @@
X */
X p->transinfo[tindex].goal_period =
X p->transinfo[tindex].user_period;
- p->transinfo[tindex].goal_offset =
- p->transinfo[tindex].user_offset;
+ if(p->features & AHC_ULTRA2)
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+ }
+ else if (p->transinfo[tindex].cur_width)
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ }
+ else
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ }
X p->needsdtr_copy |= target_mask;
X }
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Received pre-emptive SDTR message from "
+ "target.\n", p->host_no, CTL_OF_SCB(scb));
+ }
X if ( !p->transinfo[tindex].goal_offset )
X period = 255;
X if ( p->transinfo[tindex].goal_period > period )
X period = p->transinfo[tindex].goal_period;
X }
X
- syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
+ syncrate = aic7xxx_find_syncrate(p, &period, maxsync, &options);
X aic7xxx_validate_offset(p, syncrate, &offset,
X target_scsirate & WIDEXFER);
X aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+ offset, options, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
X
X /*
- * Did we drop to async? If so, are we sending a reply? If we are,
+ * Did we drop to async? Or are we sending a reply? If we are,
X * then we have to make sure that the reply value reflects the proper
X * settings so we need to set the goal values according to what
X * we need to send.
X */
- if ( (offset == 0) || (offset != saved_offset) ||
+ if ( (offset != saved_offset) ||
X ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
X (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) )
X {
- aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
- if ( offset == 0 )
- {
- p->needsdtr_copy &= ~target_mask;
- }
+ aic7xxx_set_syncrate(p, syncrate, target, channel, period, offset,
+ options, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
X }
X
X /*
@@ -5334,15 +5473,13 @@
X * go async, then send an SDTR back to the target
X */
X p->needsdtr &= ~target_mask;
- p->sdtr_pending &= ~target_mask;
- if ( ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) ==
- (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) &&
- (offset == saved_offset) )
- {
- scb->flags &= ~SCB_MSGOUT_BITS;
- }
- else
+ p->dtr_pending &= ~target_mask;
+ if ( ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) ||
+ (offset != saved_offset) )
X {
+ reply = TRUE;
+ p->dtr_pending |= target_mask;
X scb->flags &= ~SCB_MSGOUT_BITS;
X scb->flags |= SCB_MSGOUT_SDTR;
X aic_outb(p, HOST_MSG, MSG_OUT);
@@ -5376,12 +5513,11 @@
X {
X reject = TRUE;
X if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
- ((p->dev_flags[tindex] & DEVICE_PRINT_WDTR) ||
+ ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
X (aic7xxx_verbose > 0xffff)) )
X {
X printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n",
X p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width));
- p->dev_flags[tindex] &= ~DEVICE_PRINT_WDTR;
X }
X } /* We fall through on purpose */
X case MSG_EXT_WDTR_BUS_8_BIT:
@@ -5395,15 +5531,11 @@
X break;
X }
X }
- scb->flags &= ~SCB_MSGOUT_BITS;
- p->wdtr_pending &= ~target_mask;
+ p->dtr_pending &= ~target_mask;
X p->needwdtr &= ~target_mask;
X }
X else
X {
- scb->flags &= ~SCB_MSGOUT_BITS;
- scb->flags |= SCB_MSGOUT_WDTR;
- reply = TRUE;
X if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
X {
X /*
@@ -5413,13 +5545,33 @@
X */
X p->transinfo[tindex].goal_period =
X p->transinfo[tindex].user_period;
- p->transinfo[tindex].goal_offset =
- p->transinfo[tindex].user_offset;
+ if(p->transinfo[tindex].user_offset)
+ {
+ if(p->features & AHC_ULTRA2)
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+ }
+ else if( p->transinfo[tindex].user_width &&
+ (bus_width == MSG_EXT_WDTR_BUS_16_BIT) &&
+ p->features & AHC_WIDE )
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ }
+ else
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ }
+ }
X p->transinfo[tindex].goal_width =
X p->transinfo[tindex].user_width;
X p->needwdtr_copy |= target_mask;
X p->needsdtr_copy |= target_mask;
X }
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Received pre-emptive WDTR message from "
+ "target.\n", p->host_no, CTL_OF_SCB(scb));
+ }
X switch(bus_width)
X {
X default:
@@ -5441,8 +5593,11 @@
X break;
X }
X }
+ reply = TRUE;
+ scb->flags &= ~SCB_MSGOUT_BITS;
+ scb->flags |= SCB_MSGOUT_WDTR;
X p->needwdtr &= ~target_mask;
- p->wdtr_pending &= ~target_mask;
+ p->dtr_pending |= target_mask;
X aic_outb(p, HOST_MSG, MSG_OUT);
X aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
X }
@@ -5456,24 +5611,211 @@
X * supports SDTR at all. Therefore, we check needsdtr_copy instead
X * of needstr.
X */
- aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0,
+ aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
X AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
- if ( (p->needsdtr_copy & target_mask) &&
- !(p->sdtr_pending & target_mask))
+ p->needsdtr |= (p->needsdtr_copy & target_mask);
+ done = TRUE;
+ break;
+ }
+ case MSG_EXT_PPR:
+ {
+ unsigned char bus_width, trans_options, new_trans_options;
+ unsigned int period, offset;
+ unsigned char maxsync, saved_offset;
+ struct aic7xxx_syncrate *syncrate;
+
+ if (p->msg_buf[1] != MSG_EXT_PPR_LEN)
+ {
+ reject = TRUE;


+ break;
+ }
+
+ /*

+ * If we aren't on one of the new Ultra3 cards, then reject any PPR
+ * message since we can't support any option field other than 0
+ */
+ if( !(p->features & AHC_ULTRA3) )
+ {
+ reject = TRUE;
+ break;
+ }
+
+ if (p->msg_len < (MSG_EXT_PPR_LEN + 2))


+ {
+ break;
+ }
+

+ period = p->msg_buf[3];
+ offset = saved_offset = p->msg_buf[5];
+ bus_width = p->msg_buf[6];
+ trans_options = new_trans_options = p->msg_buf[7] & 0xf;
+
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Parsing PPR message (%d/%d/%d/%d)\n",
+ p->host_no, CTL_OF_SCB(scb), period, offset, bus_width,
+ trans_options);
+ }
+
+ if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
+ !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
X {
- p->needsdtr |= target_mask;
- if ( !reject && !reply )
+ if(p->features & AHC_ULTRA3)
+ {
+ maxsync = AHC_SYNCRATE_ULTRA3;
+ }
+ else
X {
- scb->flags &= ~SCB_MSGOUT_WDTR;
- if (p->transinfo[tindex].goal_period)
+ maxsync = AHC_SYNCRATE_ULTRA2;
+ }
+ }
+ else
+ {
+ maxsync = AHC_SYNCRATE_ULTRA;
+ }
+ /*
+ * We might have a device that is starting negotiation with us
+ * before we can start up negotiation with it....be prepared to
+ * have a device ask for a higher speed then we want to give it
+ * in that case
+ */
+ if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR) )
+ {
+ reply = TRUE;
+ scb->flags &= ~SCB_MSGOUT_BITS;
+ scb->flags |= SCB_MSGOUT_PPR;
+ if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+ {
+ /*
+ * Not only is the device starting this up, but it also hasn't
+ * been scanned yet, so this would likely be our TUR or our
+ * INQUIRY command at scan time, so we need to use the
+ * settings from the SEEPROM if they existed. Of course, even
+ * if we didn't find a SEEPROM, we stuffed default values into
+ * the user settings anyway, so use those in all cases.
+ */
+ p->transinfo[tindex].goal_period =
+ p->transinfo[tindex].user_period;
+ if(p->transinfo[tindex].user_offset)
X {
- p->sdtr_pending |= target_mask;
- scb->flags |= SCB_MSGOUT_SDTR;
- aic_outb(p, HOST_MSG, MSG_OUT);
- aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+ if(p->features & AHC_ULTRA2)
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+ }
+ else if( p->transinfo[tindex].user_width &&
+ (bus_width == MSG_EXT_WDTR_BUS_16_BIT) &&
+ p->features & AHC_WIDE )
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ }
+ else
+ {
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ }
+ }
+ p->transinfo[tindex].goal_width =
+ p->transinfo[tindex].user_width;
+ p->transinfo[tindex].goal_options =
+ p->transinfo[tindex].user_options;
+ p->needppr_copy |= target_mask;
+ }
+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+ {
+ printk(INFO_LEAD "Received pre-emptive PPR message from "
+ "target.\n", p->host_no, CTL_OF_SCB(scb));
+ }
+ if ( !p->transinfo[tindex].goal_offset )
+ period = 255;
+ if ( p->transinfo[tindex].goal_period > period )
+ period = p->transinfo[tindex].goal_period;
+ if ( p->transinfo[tindex].goal_options == 0 )
+ new_trans_options = 0;
+ switch(bus_width)
+ {
+ default:
+ {
+ if ( (p->features & AHC_WIDE) &&
+ (p->transinfo[tindex].goal_width ==
+ MSG_EXT_WDTR_BUS_16_BIT) )
+ {
+ bus_width = MSG_EXT_WDTR_BUS_16_BIT;
+ break;
+ }
+ } /* Fall through if we aren't a wide card */
+ case MSG_EXT_WDTR_BUS_8_BIT:
+ {
+ p->needwdtr_copy &= ~target_mask;
+ bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+ aic7xxx_set_width(p, target, channel, lun, bus_width,
+ AHC_TRANS_GOAL|AHC_TRANS_QUITE);


+ break;
+ }
+ }
+ }

+ else
+ {
+ switch(bus_width)
+ {
+ default:
+ {
+ reply = TRUE;
+ if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+ ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
+ (aic7xxx_verbose > 0xffff)) )
+ {
+ printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n",
+ p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width));
+ }
+ } /* We fall through on purpose */
+ case MSG_EXT_WDTR_BUS_8_BIT:
+ {
+ /*
+ * According to the spec, if we aren't wide, we also can't be
+ * Dual Edge so clear the options byte
+ */
+ new_trans_options = 0;
+ bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+ break;
+ }
+ case MSG_EXT_WDTR_BUS_16_BIT:
+ {
+ break;
X }
X }
X }
+
+ aic7xxx_set_width(p, target, channel, lun, bus_width,
+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+ syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
+ &new_trans_options);
+ aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
+ aic7xxx_set_syncrate(p, syncrate, target, channel, period,
+ offset, new_trans_options,
+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+
+ if( (offset != saved_offset) ||
+ (trans_options != new_trans_options) ||
+ ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) )
+ {
+ aic7xxx_set_width(p, target, channel, lun, bus_width,
+ AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+ aic7xxx_set_syncrate(p, syncrate, target, channel, period,
+ offset, new_trans_options,
+ AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+ reply = TRUE;
+ }
+ p->dtr_pending &= ~target_mask;
+ p->needppr &= ~target_mask;
+ if(reply)
+ {
+ p->dtr_pending |= target_mask;
+ scb->flags &= ~SCB_MSGOUT_BITS;
+ scb->flags |= SCB_MSGOUT_PPR;
+ aic_outb(p, HOST_MSG, MSG_OUT);
+ aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+ }
X done = TRUE;
X break;
X }
@@ -5485,7 +5827,7 @@
X } /* end of switch(p->msg_type) */
X } /* end of if (!reject && (p->msg_len > 2)) */
X
- if (reject)
+ if (!reply && reject)
X {
X aic_outb(p, MSG_MESSAGE_REJECT, MSG_OUT);
X aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
@@ -5657,12 +5999,14 @@
X if (aic7xxx_verbose & VERBOSE_RESET)
X printk(WARN_LEAD "Someone else reset the channel!!\n",
X p->host_no, channel, -1, -1);
+ if (aic7xxx_panic_on_abort)
+ aic7xxx_panic_abort(p, NULL);
X /*
X * Go through and abort all commands for the channel, but do not
X * reset the channel again.
X */
X aic7xxx_reset_channel(p, channel, /* Initiate Reset */ FALSE);
- aic7xxx_run_done_queue(p, FALSE);
+ aic7xxx_run_done_queue(p, TRUE);
X scb = NULL;
X }
X else if ( ((status & BUSFREE) != 0) && ((status & SELTO) == 0) )
@@ -5698,7 +6042,7 @@
X CTL_OF_SCB(scb), scb->hscb->tag);
X aic7xxx_reset_device(p, target, channel, ALL_LUNS,
X (message == MSG_ABORT) ? SCB_LIST_NULL : scb->hscb->tag );
- aic7xxx_run_done_queue(p, FALSE);
+ aic7xxx_run_done_queue(p, TRUE);
X scb = NULL;
X printerror = 0;
X }
@@ -5709,6 +6053,22 @@
X printerror = 0;
X }
X }
+ if ( (scb != NULL) &&
+ (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)]) )
+ {
+ /*
+ * This might be a SCSI-3 device that is dropping the bus due to
+ * errors and signalling that we should reduce the transfer speed.
+ * All we have to do is complete this command (since it's a negotiation
+ * command already) and the checksum routine should flag an error and
+ * reduce the speed setting and renegotiate. We call the reset routing
+ * just to clean out the hardware from this scb.
+ */
+ printerror = 0;
+ aic7xxx_reset_device(p, target, channel, ALL_LUNS, scb->hscb->tag);
+ aic7xxx_run_done_queue(p, TRUE);
+ scb = NULL;
+ }
X if (printerror != 0)
X {
X if (scb != NULL)
@@ -5724,7 +6084,12 @@
X tag = SCB_LIST_NULL;
X }
X aic7xxx_reset_device(p, target, channel, ALL_LUNS, tag);
- aic7xxx_run_done_queue(p, FALSE);
+ aic7xxx_run_done_queue(p, TRUE);
+ }
+ else
+ {
+ aic7xxx_reset_device(p, target, channel, ALL_LUNS, SCB_LIST_NULL);
+ aic7xxx_run_done_queue(p, TRUE);
X }
X printk(INFO_LEAD "Unexpected busfree, LASTPHASE = 0x%x, "
X "SEQADDR = 0x%x\n", p->host_no, channel, target, -1, lastphase,
@@ -5829,12 +6194,26 @@
X cmd->result = 0;
X scb = NULL;
X }
+ if (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)])
+ {
+ /*
+ * Turn off the needsdtr, needwdtr, and needppr bits since this device
+ * doesn't seem to exist.
+ */
+ p->needppr &= ~(0x01 << TARGET_INDEX(scb->cmd));
+ p->needppr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
+ p->needsdtr &= ~(0x01 << TARGET_INDEX(scb->cmd));
+ p->needsdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
+ p->needwdtr &= ~(0x01 << TARGET_INDEX(scb->cmd));
+ p->needwdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
+ }
X }
X /*
X * Restarting the sequencer will stop the selection and make sure devices
X * are allowed to reselect in.
X */
X aic_outb(p, 0, SCSISEQ);
+ aic_outb(p, CLRSELINGO, CLRSINT0);
X aic_outb(p, aic_inb(p, SIMODE1) & ~(ENREQINIT|ENBUSFREE), SIMODE1);
X p->flags &= ~AHC_HANDLING_REQINITS;
X aic_outb(p, CLRSELTIMEO | CLRBUSFREE, CLRSINT1);
@@ -5868,6 +6247,8 @@
X Scsi_Cmnd *cmd;
X unsigned char mesg_out = MSG_NOOP;
X unsigned char lastphase = aic_inb(p, LASTPHASE);
+ unsigned char sstat2 = aic_inb(p, SSTAT2);
+ unsigned char tindex = TARGET_INDEX(scb->cmd);
X
X cmd = scb->cmd;
X switch (lastphase)
@@ -5898,12 +6279,81 @@
X break;
X }
X
- /*
- * A parity error has occurred during a data
- * transfer phase. Flag it and continue.
- */
- printk(WARN_LEAD "Parity error during %s phase.\n",
- p->host_no, CTL_OF_SCB(scb), phase);
+ /*
+ * A parity error has occurred during a data
+ * transfer phase. Flag it and continue.
+ */
+ if( (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) && (lastphase == P_DATAIN) )
+ {
+ printk(WARN_LEAD "CRC error during %s phase.\n",
+ p->host_no, CTL_OF_SCB(scb), phase);
+ if(sstat2 & CRCVALERR)
+ {
+ printk(WARN_LEAD " CRC error in intermediate CRC packet.\n",
+ p->host_no, CTL_OF_SCB(scb));
+ }
+ if(sstat2 & CRCENDERR)
+ {
+ printk(WARN_LEAD " CRC error in ending CRC packet.\n",
+ p->host_no, CTL_OF_SCB(scb));
+ }
+ if(sstat2 & CRCREQERR)
+ {
+ printk(WARN_LEAD " Target incorrectly requested a CRC packet.\n",
+ p->host_no, CTL_OF_SCB(scb));
+ }
+ if(sstat2 & DUAL_EDGE_ERROR)
+ {
+ printk(WARN_LEAD " Dual Edge transmission error.\n",
+ p->host_no, CTL_OF_SCB(scb));
+ }
+ }
+ else
+ {
+ printk(WARN_LEAD "Parity error during %s phase.\n",
+ p->host_no, CTL_OF_SCB(scb), phase);
+ }
+
+ if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
+ {
+ struct aic7xxx_syncrate *syncrate;
+ unsigned int period = p->transinfo[tindex].cur_period;
+ unsigned char options = p->transinfo[tindex].cur_options;
+ /*
+ * oops, we had a failure, lower the transfer rate and try again. It's
+ * worth noting here that it might be wise to also check for typical
+ * wide setting on narrow cable type problems and try disabling wide
+ * instead of slowing down if those exist. That's hard to do with simple
+ * checksums though.
+ */
+ if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
+ {
+ syncrate++;
+ if( (syncrate->rate[0] != NULL) &&
+ (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
+ {
+ p->transinfo[tindex].goal_period = syncrate->period;
+ if( !(syncrate->sxfr_ultra2 & 0x40) )
+ {
+ p->transinfo[tindex].goal_options = 0;
+ }
+ }
+ else
+ {
+ p->transinfo[tindex].goal_offset = 0;
+ p->transinfo[tindex].goal_period = 0;
+ p->transinfo[tindex].goal_options = 0;
+ }
+ p->needppr |= (p->needppr_copy & (1<<tindex));
+ p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+ p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+ }
+ p->dev_flags[tindex] &= ~DEVICE_PARITY_ERROR;
+ }
+ else
+ {
+ p->dev_flags[tindex] |= DEVICE_PARITY_ERROR;
+ }
X
X /*
X * We've set the hardware to assert ATN if we get a parity
@@ -6072,13 +6522,6 @@
X printk("HSCB %d bad, SCB_NEXT points to self.\n", i);
X bogus = TRUE;
X }
- temp = aic_inb(p, SCB_PREV);
- if ((temp != SCB_LIST_NULL) &&
- (temp >= p->scb_data->maxhscbs))
- {
- printk("HSCB %d bad, SCB_PREV invalid(%d).\n", i, temp);
- bogus = TRUE;
- }
X if (scb_status[i] == 0)
X lost++;
X if (lost > 1)
@@ -6163,7 +6606,7 @@
X unsigned char scb_index;
X
X #ifdef AIC7XXX_VERBOSE_DEBUGGING
- if(aic7xxx_verbose > 0xffff)
+ if( (p->isr_count < 16) && (aic7xxx_verbose > 0xffff) )
X printk(INFO_LEAD "Command Complete Int.\n", p->host_no, -1, -1, -1);
X #endif
X
@@ -6368,7 +6811,7 @@
X * Determines the queue depth for a given device. There are two ways
X * a queue depth can be obtained for a tagged queueing device. One
X * way is the default queue depth which is determined by whether
- * AIC7XXX_CMDS_PER_LUN is defined. If it is defined, then it is used
+ * AIC7XXX_CMDS_PER_DEVICE is defined. If it is defined, then it is used
X * as the default queue depth. Otherwise, we use either 4 or 8 as the
X * default queue depth (dependent on the number of hardware SCBs).
X * The other way we determine queue depth is through the use of the
@@ -6396,7 +6839,7 @@
X {
X int tag_enabled = TRUE;
X
- default_depth = AIC7XXX_CMDS_PER_LUN;
+ default_depth = AIC7XXX_CMDS_PER_DEVICE;
X
X if (!(p->discenable & target_mask))
X {
@@ -6958,7 +7401,7 @@
X }
X printk("\n");
X #endif
- if (checksum != scarray[len - 1])
+ if ( (checksum != scarray[len - 1]) || (checksum == 0) )
X {
X return (0);
X }
@@ -7371,7 +7814,6 @@
X aic_outb(p, i, SCBPTR);
X aic_outb(p, 0, SCB_CONTROL); /* Clear the control byte. */
X aic_outb(p, i + 1, SCB_NEXT); /* Set the next pointer. */
- aic_outb(p, i - 1, SCB_PREV); /* Set the prev pointer. */
X aic_outb(p, SCB_LIST_NULL, SCB_TAG); /* Make the tag invalid. */
X aic_outb(p, SCB_LIST_NULL, SCB_BUSYTARGETS); /* no busy untagged */
X aic_outb(p, SCB_LIST_NULL, SCB_BUSYTARGETS+1);/* targets active yet */
@@ -7840,6 +8282,11 @@
X */
X aic7xxx_loadseq(p);
X
+ /*
+ * Make sure the AUTOFLUSHDIS bit is *not* set in the SBLKCTL register
+ */
+ aic_outb(p, aic_inb(p, SBLKCTL) & ~AUTOFLUSHDIS, SBLKCTL);
+
X if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 )
X {
X aic_outb(p, ENABLE, BCTL); /* Enable the boards BUS drivers. */
@@ -8035,6 +8482,7 @@
X {
X p->transinfo[i].goal_period = 0;
X p->transinfo[i].goal_offset = 0;
+ p->transinfo[i].goal_options = 0;
X p->transinfo[i].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
X }
X DRIVER_LOCK_INIT
@@ -8090,10 +8538,14 @@
X */
X for (i = 0; i < MAX_TARGETS; i++)
X {
- if(p->dev_wdtr_cmnd[i])
- kfree(p->dev_wdtr_cmnd[i]);
- if(p->dev_sdtr_cmnd[i])
- kfree(p->dev_sdtr_cmnd[i]);
+ if(p->dev_dtr_cmnd[i])
+ {
+ if(p->dev_dtr_cmnd[i]->request_buffer)
+ {
+ kfree(p->dev_dtr_cmnd[i]->request_buffer);
+ }
+ kfree(p->dev_dtr_cmnd[i]);
+ }
X }
X
X }
@@ -8184,14 +8636,16 @@
X {
X printk("aic7xxx: Using leftover BIOS values.\n");
X }
- if ( *sxfrctl1 & STPWEN )
+ if ( ((p->chip & ~AHC_CHIPID_MASK) == AHC_PCI) && (*sxfrctl1 & STPWEN) )
X {
X p->flags |= AHC_TERM_ENB_SE_LOW | AHC_TERM_ENB_SE_HIGH;
X sc->adapter_control &= ~CFAUTOTERM;
X sc->adapter_control |= CFSTERM | CFWSTERM | CFLVDSTERM;
X }
X if (aic7xxx_extended)
- p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
+ p->flags |= (AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
+ else
+ p->flags &= ~(AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
X }
X else
X {
@@ -8256,8 +8710,7 @@
X * Limit to 16 targets just in case. The 2842 for one is known to
X * blow the max_targets setting, future cards might also.
X */
- max_targets = MIN(sc->max_targets & CFMAXTARG,
- ((p->features & (AHC_TWIN | AHC_WIDE)) ? 16 : 8));
+ max_targets = ((p->features & (AHC_TWIN | AHC_WIDE)) ? 16 : 8);
X
X if (have_seeprom)
X {
@@ -8279,7 +8732,7 @@
X mask = (0x01 << i);
X if (!have_seeprom)
X {
- if(aic_inb(p, SCSISEQ) != 0)
+ if (aic_inb(p, SCSISEQ) != 0)
X {
X /*
X * OK...the BIOS set things up and left behind the settings we need.
@@ -8323,7 +8776,9 @@
X sc->device_flags[i] = CFDISC;
X if (p->features & AHC_WIDE)
X sc->device_flags[i] |= CFWIDEB;
- if (p->features & AHC_ULTRA2)
+ if (p->features & AHC_ULTRA3)
+ sc->device_flags[i] |= 2;
+ else if (p->features & AHC_ULTRA2)
X sc->device_flags[i] |= 3;
X else if (p->features & AHC_ULTRA)
X sc->device_flags[i] |= CFSYNCHISULTRA;
@@ -8339,20 +8794,30 @@
X }
X if (p->flags & AHC_NEWEEPROM_FMT)
X {
- if (sc->device_flags[i] & CFSYNCHISULTRA)
- {
- p->ultraenb |= mask;
- }
- else if (sc->device_flags[i] & CFNEWULTRAFORMAT)
+ if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) &&
+ !(p->features & AHC_ULTRA2) )
X {
- if ( ((sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03) &&
- !(p->features & AHC_ULTRA2) )
+ /*
+ * I know of two different Ultra BIOSes that do this differently.
+ * One on the Gigabyte 6BXU mb that wants flags[i] & CFXFER to
+ * be == to 0x03 and SYNCISULTRA to be true to mean 40MByte/s
+ * while on the IBM Netfinity 5000 they want the same thing
+ * to be something else, while flags[i] & CFXFER == 0x03 and
+ * SYNCISULTRA false should be 40MByte/s. So, we set both to
+ * 40MByte/s and the lower speeds be damned. People will have
+ * to select around the conversely mapped lower speeds in order
+ * to select lower speeds on these boards.
+ */
+ if ((sc->device_flags[i] & (CFXFER)) == 0x03)
X {
X sc->device_flags[i] &= ~CFXFER;
X sc->device_flags[i] |= CFSYNCHISULTRA;
- p->ultraenb |= mask;
X }
X }


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part10

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


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

if test "$Scheck" != 10; then


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

+
+ MOD_INC_USE_COUNT;
X
X /* Ready to play! */
X dev->tbusy = 0;
X dev->interrupt = 0;
X dev->start = 1;
X
- MOD_INC_USE_COUNT;
-
- irport_start(iobase);
+ /* Change speed to make sure dongles follow us again */
+ if (idev->change_speed)
+ idev->change_speed(idev, 9600);
X
X return 0;
X }
@@ -558,12 +619,12 @@
X
X iobase = idev->io.iobase2;
X
- irport_stop(iobase);
-
X /* Stop device */
X dev->tbusy = 1;
X dev->start = 0;
X
+ irport_stop(idev, iobase);
+
X free_irq(idev->io.irq2, idev);
X
X MOD_DEC_USE_COUNT;
@@ -571,12 +632,32 @@


X return 0;
X }
X

-static void irport_wait_until_sent(struct irda_device *idev)
+/*
+ * Function irport_wait_until_sent (idev)
+ *
+ * Delay exectution until finished transmitting
+ *
+ */
+void irport_wait_until_sent(struct irda_device *idev)
X {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(60*HZ/1000);
+ int iobase;
+
+ iobase = idev->io.iobase2;
+
+ /* Wait until Tx FIFO is empty */
+ while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+ DEBUG(2, __FUNCTION__ "(), waiting!\n");
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(MSECS_TO_JIFFIES(60));
+ }
X }
X
+/*
+ * Function irport_is_receiving (idev)
+ *
+ * Returns true is we are currently receiving data
+ *
+ */
X static int irport_is_receiving(struct irda_device *idev)
X {
X return (idev->rx_buff.state != OUTSIDE_FRAME);


@@ -635,6 +716,9 @@
X

X MODULE_PARM(io, "1-4i");
X MODULE_PARM(irq, "1-4i");
+
+MODULE_AUTHOR("Dag Brattli <da...@cs.uit.no>");
+MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode");
X
X /*
X * Function cleanup_module (void)
diff -u --recursive --new-file v2.3.5/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.3.5/linux/drivers/net/irda/litelink.c Mon May 31 22:28:05 1999
+++ linux/drivers/net/irda/litelink.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@
X * Status: Stable
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Fri May 7 12:50:33 1999
- * Modified at: Mon May 10 15:12:18 1999
+ * Modified at: Wed May 19 07:25:15 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -33,19 +33,19 @@
X #include <linux/tty.h>
X #include <linux/sched.h>
X #include <linux/init.h>
-#include <asm/ioctls.h>
-#include <asm/uaccess.h>
X
X #include <net/irda/irda.h>
X #include <net/irda/irmod.h>
X #include <net/irda/irda_device.h>
X #include <net/irda/dongle.h>
X
-static void litelink_reset(struct irda_device *dev, int unused);
+#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
+#define MAX_DELAY 10000 /* 1 ms */
+
X static void litelink_open(struct irda_device *idev, int type);
X 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_change_speed(struct irda_device *dev, int baudrate);
+static void litelink_reset(struct irda_device *dev);
X static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
X
X /* These are the baudrates supported */
@@ -105,13 +105,13 @@
X irda_device_set_dtr_rts(idev, TRUE, FALSE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X
X /* Go back to normal mode */
X irda_device_set_dtr_rts(idev, TRUE, TRUE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X
X /* Cycle through avaiable baudrates until we reach the correct one */
X for (i=0; i<5 && baud_rates[i] != baudrate; i++) {
@@ -120,13 +120,13 @@
X irda_device_set_dtr_rts(idev, FALSE, TRUE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X
X /* Set DTR, Set RTS */
X irda_device_set_dtr_rts(idev, TRUE, TRUE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X }
X }
X
@@ -137,11 +137,8 @@
X * called with a process context!
X *
X */
-static void litelink_reset(struct irda_device *idev, int unused)
+static void litelink_reset(struct irda_device *idev)
X {
- struct irtty_cb *self;
- struct tty_struct *tty;
-
X ASSERT(idev != NULL, return;);
X ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
X
@@ -149,19 +146,19 @@
X irda_device_set_dtr_rts(idev, TRUE, TRUE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X
X /* Clear RTS to reset dongle */
X irda_device_set_dtr_rts(idev, TRUE, FALSE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X
X /* Go back to normal mode */
X irda_device_set_dtr_rts(idev, TRUE, TRUE);
X
X /* Sleep a minimum of 15 us */
- udelay(15);
+ udelay(MIN_DELAY);
X
X /* This dongles speed defaults to 115200 bps */
X idev->qos.baud_rate.value = 115200;
@@ -173,7 +170,7 @@
X * Initialize QoS capabilities
X *
X */
-static void litelink_init_qos( struct irda_device *idev, struct qos_info *qos)
+static void litelink_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 qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
diff -u --recursive --new-file v2.3.5/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.5/linux/drivers/net/irda/pc87108.c Mon May 31 22:28:05 1999
+++ linux/drivers/net/irda/pc87108.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Sun May 9 12:57:46 1999
+ * Modified at: Mon May 24 15:19:21 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>
@@ -72,7 +72,7 @@
X #define CHIP_IO_EXTENT 8
X
X static unsigned int io[] = { 0x2f8, ~0, ~0, ~0 };
-static unsigned int io2[] = { 0x150, 0, 0, 0};
+static unsigned int io2[] = { 0x150, 0, 0, 0 };
X static unsigned int irq[] = { 3, 0, 0, 0 };
X static unsigned int dma[] = { 0, 0, 0, 0 };
X
@@ -98,28 +98,28 @@
X };
X
X /* Some prototypes */
-static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma);
+static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
+ unsigned int irq, unsigned int dma);
X #ifdef MODULE
-static int pc87108_close( struct irda_device *idev);
+static int pc87108_close(struct irda_device *idev);
X #endif /* MODULE */
-static int pc87108_probe( int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive( struct irda_device *idev);
-static int pc87108_dma_receive( struct irda_device *idev);
+static int pc87108_probe(int iobase, int board_addr, int irq, int dma);
+static void pc87108_pio_receive(struct irda_device *idev);
+static int pc87108_dma_receive(struct irda_device *idev);
X static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
-static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev);
-static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write( struct irda_device *idev, int iobase);
-static void pc87108_change_speed( struct irda_device *idev, int baud);
+static int pc87108_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void pc87108_dma_write(struct irda_device *idev, int iobase);
+static void pc87108_change_speed(struct irda_device *idev, int baud);
X static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void pc87108_wait_until_sent( struct irda_device *idev);
-static int pc87108_is_receiving( struct irda_device *idev);
-static int pc87108_read_dongle_id ( int iobase);
-static void pc87108_init_dongle_interface ( int iobase, int dongle_id);
-
-static int pc87108_net_init( struct device *dev);
-static int pc87108_net_open( struct device *dev);
-static int pc87108_net_close( struct device *dev);
+static void pc87108_wait_until_sent(struct irda_device *idev);
+static int pc87108_is_receiving(struct irda_device *idev);
+static int pc87108_read_dongle_id (int iobase);
+static void pc87108_init_dongle_interface (int iobase, int dongle_id);
+
+static int pc87108_net_init(struct device *dev);
+static int pc87108_net_open(struct device *dev);
+static int pc87108_net_close(struct device *dev);
X
X /*
X * Function pc87108_init ()
@@ -131,11 +131,11 @@
X {
X int i;
X
- for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+ for (i=0; (io[i] < 2000) && (i < 4); i++) {
X int ioaddr = io[i];
X if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
X continue;
- if (pc87108_open( i, io[i], io2[i], irq[i], dma[i]) == 0)
+ if (pc87108_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
X return 0;
X }
X return -ENODEV;
@@ -167,29 +167,29 @@
X * Open driver instance
X *
X */
-static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma)
+static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
+ unsigned int irq, unsigned int dma)
X {
X struct pc87108 *self;
X struct irda_device *idev;
X int ret;
X int dongle_id;
X
- DEBUG( 0, __FUNCTION__ "()\n");
+ DEBUG(0, __FUNCTION__ "()\n");
X
- if (( dongle_id = pc87108_probe( iobase, board_addr, irq, dma)) == -1)
+ if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
X return -1;
X
X /*
X * Allocate new instance of the driver
X */
- self = kmalloc( sizeof(struct pc87108), GFP_KERNEL);
- if ( self == NULL) {
- printk( KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
+ self = kmalloc(sizeof(struct pc87108), GFP_KERNEL);
+ if (self == NULL) {
+ printk(KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
X return -ENOMEM;
X }
- memset( self, 0, sizeof(struct pc87108));
+ memset(self, 0, sizeof(struct pc87108));
X
X /* Need to store self somewhere */
X dev_self[i] = self;
@@ -204,24 +204,24 @@
X idev->io.fifo_size = 32;
X
X /* Lock the port that we need */
- ret = check_region( idev->io.iobase, idev->io.io_ext);
- if ( ret < 0) {
- DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- idev->io.iobase);
+ ret = check_region(idev->io.iobase, idev->io.io_ext);
+ if (ret < 0) {
+ DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ idev->io.iobase);
X /* pc87108_cleanup( self->idev); */
X return -ENODEV;
X }
- request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+ request_region(idev->io.iobase, idev->io.io_ext, idev->name);
X
X /* Initialize QoS for this device */
- irda_init_max_qos_capabilies( &idev->qos);
+ irda_init_max_qos_capabilies(&idev->qos);
X
X /* The only value we must override it the baudrate */
X idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
X IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
X
X idev->qos.min_turn_time.bits = qos_mtt_bits;
- irda_qos_bits_to_value( &idev->qos);
+ irda_qos_bits_to_value(&idev->qos);
X
X idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
X
@@ -245,10 +245,10 @@
X idev->netdev.stop = pc87108_net_close;
X
X idev->io.dongle_id = dongle_id;
- pc87108_init_dongle_interface( iobase, dongle_id);
+ pc87108_init_dongle_interface(iobase, dongle_id);
X
X /* Open the IrDA device */
- irda_device_open( idev, driver_name, self);
+ irda_device_open(idev, driver_name, self);
X
X return 0;
X }
@@ -267,15 +267,14 @@
X
X DEBUG( 4, __FUNCTION__ "()\n");
X
- ASSERT( idev != NULL, return -1;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ ASSERT(idev != NULL, return -1;);
+ ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
X
X iobase = idev->io.iobase;
X self = (struct pc87108 *) idev->priv;
X
X /* Release the PORT that this driver is using */
- DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n",
- idev->io.iobase);
+ DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
X release_region(idev->io.iobase, idev->io.io_ext);
X
X irda_device_close(idev);
@@ -292,22 +291,22 @@
X * Returns non-negative on success.
X *
X */
-static int pc87108_probe( int iobase, int board_addr, int irq, int dma)
+static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
X {
X int version;
X __u8 temp=0;
X int dongle_id;
X
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
X
X /* Base Address and Interrupt Control Register BAIC */
X outb(0, board_addr);
- switch ( iobase) {
- case 0x3E8: outb( 0x14, board_addr+1); break;
- case 0x2E8: outb( 0x15, board_addr+1); break;
- case 0x3F8: outb( 0x16, board_addr+1); break;
- case 0x2F8: outb( 0x17, board_addr+1); break;
- default: DEBUG(0, __FUNCTION__ "(), invalid base_address");
+ switch (iobase) {
+ case 0x3E8: outb(0x14, board_addr+1); break;
+ case 0x2E8: outb(0x15, board_addr+1); break;
+ case 0x3F8: outb(0x16, board_addr+1); break;
+ case 0x2F8: outb(0x17, board_addr+1); break;
+ default: ERROR(__FUNCTION__ "(), invalid base_address");
X }
X
X /* Control Signal Routing Register CSRT */
@@ -319,74 +318,73 @@
X case 9: temp = 0x05; break;
X case 11: temp = 0x06; break;
X case 15: temp = 0x07; break;
- default: DEBUG( 0, __FUNCTION__ "(), invalid irq");
+ default: ERROR(__FUNCTION__ "(), invalid irq");
X }
- outb( 1, board_addr);
-
+ outb(1, board_addr);
+
X switch (dma) {
- case 0: outb( 0x08+temp, board_addr+1); break;
- case 1: outb( 0x10+temp, board_addr+1); break;
- case 3: outb( 0x18+temp, board_addr+1); break;
+ case 0: outb(0x08+temp, board_addr+1); break;
+ case 1: outb(0x10+temp, board_addr+1); break;
+ case 3: outb(0x18+temp, board_addr+1); break;
X default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
X }
X
X /* Mode Control Register MCTL */
- outb( 2, board_addr);
- outb( 0x03, board_addr+1);
+ outb(2, board_addr);
+ outb(0x03, board_addr+1);
X
X /* read the Module ID */
- switch_bank( iobase, BANK3);
- version = inb( iobase+MID);
+ switch_bank(iobase, BANK3);
+ version = inb(iobase+MID);
X
X /* should be 0x2? */
- if (0x20 != (version & 0xf0))
- {
- DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+ if (0x20 != (version & 0xf0)) {
+ ERROR(__FUNCTION__ "(), Wrong chip version %02x\n", version);
X return -1;
X }
X
X /* Switch to advanced mode */
X switch_bank( iobase, BANK2);
- outb( ECR1_EXT_SL, iobase+ECR1);
- switch_bank( iobase, BANK0);
+ outb(ECR1_EXT_SL, iobase+ECR1);
+ switch_bank(iobase, BANK0);
X
- dongle_id = pc87108_read_dongle_id( iobase);
- DEBUG( 0, __FUNCTION__ "(), Found dongle: %s\n",
- dongle_types[ dongle_id]);
+ dongle_id = pc87108_read_dongle_id(iobase);
+ DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n",
+ dongle_types[ dongle_id]);
X
X /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
- switch_bank( iobase, BANK0);
- outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+ switch_bank(iobase, BANK0);
+ outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
X
X /* Set FIFO size to 32 */
- switch_bank( iobase, BANK2);
- outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+ switch_bank(iobase, BANK2);
+ outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
X
X /* IRCR2: FEND_MD is set */
- switch_bank( iobase, BANK5);
- outb( 0x2a, iobase+4);
+ switch_bank(iobase, BANK5);
+ outb(0x2a, iobase+4);
X
X /* Make sure that some defaults are OK */
- switch_bank( iobase, BANK6);
- outb( 0x20, iobase+0); /* Set 32 bits FIR CRC */
- outb( 0x0a, iobase+1); /* Set MIR pulse width */
- outb( 0x0d, iobase+2); /* Set SIR pulse width */
- outb( 0x2a, iobase+4); /* Set beginning frag, and preamble length */
+ switch_bank(iobase, BANK6);
+ outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
+ outb(0x0a, iobase+1); /* Set MIR pulse width */
+ outb(0x0d, iobase+2); /* Set SIR pulse width */
+ outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
X
X /* Receiver frame length */
- switch_bank( iobase, BANK4);
- outb( 2048 & 0xff, iobase+6);
- outb(( 2048 >> 8) & 0x1f, iobase+7);
+ switch_bank(iobase, BANK4);
+ outb(2048 & 0xff, iobase+6);
+ outb((2048 >> 8) & 0x1f, iobase+7);
X
X /* Transmitter frame length */
- outb( 2048 & 0xff, iobase+4);
- outb(( 2048 >> 8) & 0x1f, iobase+5);
+ outb(2048 & 0xff, iobase+4);
+ outb((2048 >> 8) & 0x1f, iobase+5);
X
- DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version);
+ DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
X
X /* Enable receive interrupts */
- switch_bank( iobase, BANK0);
- outb( IER_RXHDL_IE, iobase+IER);
+ switch_bank(iobase, BANK0);
+ outb(IER_RXHDL_IE, iobase+IER);
X
X return dongle_id;
X }
@@ -409,10 +407,10 @@
X bank = inb( iobase+BSR);
X
X /* Select Bank 7 */
- switch_bank( iobase, BANK7);
+ switch_bank(iobase, BANK7);
X
X /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
- outb( 0x00, iobase+7);
+ outb(0x00, iobase+7);
X
X /* ID0, 1, and 2 are pulled up/down very slowly */
X udelay(50);
@@ -421,16 +419,16 @@
X dongle_id = inb( iobase+4) & 0x0f;
X
X #ifdef BROKEN_DONGLE_ID
- if ( dongle_id == 0x0a)
+ if (dongle_id == 0x0a)
X dongle_id = 0x09;
X #endif
-
+
X /* Go back to bank 0 before returning */
- switch_bank( iobase, BANK0);
+ switch_bank(iobase, BANK0);
X
- DEBUG( 0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
+ DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
X
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
X
X return dongle_id;
X }
@@ -443,7 +441,7 @@
X * power-on/reset. It also needs to be used whenever you suspect that
X * the dongle is changed.
X */
-static void pc87108_init_dongle_interface ( int iobase, int dongle_id)
+static void pc87108_init_dongle_interface (int iobase, int dongle_id)
X {
X int bank;
X
@@ -818,11 +816,11 @@
X iobase+ECR1);
X
X /* Enable DMA */
- switch_bank( iobase, BANK0);
- outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
X
X /* Restore bank register */
- outb( bsr, iobase+BSR);
+ outb(bsr, iobase+BSR);
X }
X
X /*
@@ -832,7 +830,7 @@
X * got transfered
X *
X */
-static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size)
+static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
X {
X int actual = 0;
X __u8 bank;
@@ -851,16 +849,16 @@
X }
X
X /* Fill FIFO with current frame */
- while (( fifo_size-- > 0) && (actual < len)) {
+ while ((fifo_size-- > 0) && (actual < len)) {
X /* Transmit next byte */
- outb( buf[actual++], iobase+TXD);
+ outb(buf[actual++], iobase+TXD);
X }
X
- DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
- fifo_size, actual, len);
+ DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ fifo_size, actual, len);
X
X /* Restore bank */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
X
X return actual;
X }
@@ -1466,6 +1464,9 @@
X MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver");
X
X MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
X
X /*
X * Function init_module (void)
diff -u --recursive --new-file v2.3.5/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.5/linux/drivers/net/irda/smc-ircc.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/smc-ircc.c Mon Jun 7 16:18:58 1999
@@ -0,0 +1,969 @@
+/*********************************************************************
+ *
+ * Filename: smc-ircc.c
+ * Version: 0.1
+ * Description: Driver for the SMC Infrared Communications Controller (SMC)
+ * Status: Experimental.
+ * Author: Thomas Davis (tad...@jps.net)
+ * Created at:
+ * Modified at: Wed May 19 15:30:08 1999
+ * Modified by: Dag Brattli <da...@cs.uit.no>
+ *
+ * Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.


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

+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * I, Thomas Davis, admit no liability nor provide warranty for any
+ * of this software. This material is provided "AS-IS" and at no charge.
+ *
+ * Applicable Models : Fujitsu Lifebook 635t
+ * Sony PCG-505TX (gets DMA wrong.)
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/smc-ircc.h>
+#include <net/irda/irport.h>
+
+static char *driver_name = "smc-ircc";
+
+#define CHIP_IO_EXTENT 8
+
+static unsigned int io[] = { 0x2e8, 0x140, ~0, ~0 };
+static unsigned int io2[] = { 0x2f8, 0x3e8, 0, 0};
+
+static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+
+/* Some prototypes */
+static int ircc_open( int i, unsigned int iobase, unsigned int board_addr);
+static int ircc_close( struct irda_device *idev);
+static int ircc_probe( int iobase, int board_addr);
+static int ircc_dma_receive( struct irda_device *idev);
+static int ircc_dma_receive_complete(struct irda_device *idev, int iobase);
+static int ircc_hard_xmit( struct sk_buff *skb, struct device *dev);
+static void ircc_dma_write( struct irda_device *idev, int iobase);
+static void ircc_change_speed( struct irda_device *idev, int baud);
+static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void ircc_wait_until_sent( struct irda_device *idev);
+static int ircc_is_receiving( struct irda_device *idev);
+
+static int ircc_net_init( struct device *dev);
+static int ircc_net_open( struct device *dev);
+static int ircc_net_close( struct device *dev);
+
+static int ircc_debug=3;
+static int ircc_irq=255;
+static int ircc_dma=255;
+
+static inline void register_bank(int port, int bank)
+{
+ outb(((inb(port+UART_MASTER) & 0xF0) | (bank & 0x07)),
+ port+UART_MASTER);
+}
+
+static inline unsigned int serial_in(int port, int offset)
+{
+ return inb(port+offset);
+}
+
+static inline void serial_out(int port, int offset, int value)
+{
+ outb(value, port+offset);
+}
+
+/*
+ * Function ircc_init ()
+ *
+ * Initialize chip. Just try to find out how many chips we are dealing with
+ * and where they are
+ */
+__initfunc(int ircc_init(void))
+{
+ int i;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+ int ioaddr = io[i];
+ if (check_region(ioaddr, CHIP_IO_EXTENT))
+ continue;
+ if (ircc_open( i, io[i], io2[i]) == 0)
+ return 0;
+ }
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+


+ return -ENODEV;
+}
+

+/*
+ * Function ircc_cleanup ()
+ *
+ * Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void ircc_cleanup(void)
+{
+ int i;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ for ( i=0; i < 4; i++) {
+ if ( dev_self[i])
+ ircc_close( &(dev_self[i]->idev));
+ }
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+}
+#endif /* MODULE */

+
+/*
+ * Function ircc_open (iobase, irq)
+ *
+ * Open driver instance
+ *
+ */
+static int ircc_open( int i, unsigned int iobase, unsigned int iobase2)
+{
+ struct ircc_cb *self;
+ struct irda_device *idev;
+ int ret;
+ int config;
+
+ DEBUG( ircc_debug, __FUNCTION__ " -->\n");
+
+ if ((config = ircc_probe( iobase, iobase2)) == -1) {
+ DEBUG(ircc_debug,
+ __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
+ return -1;
+ }
+
+ /*
+ * Allocate new instance of the driver
+ */
+ self = kmalloc( sizeof(struct ircc_cb), GFP_KERNEL);
+ if ( self == NULL) {
+ printk( KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+ return -ENOMEM;
+ }
+ memset(self, 0, sizeof(struct ircc_cb));
+
+ /* Need to store self somewhere */
+ dev_self[i] = self;
+
+ idev = &self->idev;
+
+ /* Initialize IO */
+ idev->io.iobase = iobase;
+ idev->io.iobase2 = iobase2; /* Used by irport */
+ idev->io.irq = config >> 4 & 0x0f;
+ if (ircc_irq < 255) {
+ printk(KERN_INFO "smc: Overriding IRQ - chip says %d, using %d\n",
+ idev->io.irq, ircc_irq);
+ idev->io.irq = ircc_irq;
+ }
+ idev->io.io_ext = CHIP_IO_EXTENT;
+ idev->io.io_ext2 = 8; /* Used by irport */
+ idev->io.dma = config & 0x0f;
+ if (ircc_dma < 255) {
+ printk(KERN_INFO "smc: Overriding DMA - chip says %d, using %d\n",
+ idev->io.dma, ircc_dma);
+ idev->io.dma = ircc_dma;
+ }
+ idev->io.fifo_size = 16;
+
+ /* Lock the port that we need */
+ ret = check_region( idev->io.iobase, idev->io.io_ext);
+ if ( ret < 0) {
+ DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+ idev->io.iobase);
+ /* ircc_cleanup( self->idev); */
+ return -ENODEV;
+ }
+ ret = check_region( idev->io.iobase2, idev->io.io_ext2);
+ if ( ret < 0) {
+ DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+ idev->io.iobase2);
+ /* ircc_cleanup( self->idev); */
+ return -ENODEV;
+ }
+ request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+ request_region( idev->io.iobase2, idev->io.io_ext2, idev->name);
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies( &idev->qos);
+
+#if 1
+ /* The only value we must override it the baudrate */
+ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+#else
+ /* The only value we must override it the baudrate */
+ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200;
+#endif
+
+ idev->qos.min_turn_time.bits = 0x07;
+ irda_qos_bits_to_value( &idev->qos);
+
+ idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+
+ /* Specify which buffer allocation policy we need */
+ idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+ idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+ idev->rx_buff.truesize = 4000;
+ idev->tx_buff.truesize = 4000;
+
+ /* Initialize callbacks */
+ idev->change_speed = ircc_change_speed;
+ idev->wait_until_sent = ircc_wait_until_sent;
+ idev->is_receiving = ircc_is_receiving;
+
+ /* Override the network functions we need to use */
+ idev->netdev.init = ircc_net_init;
+ idev->netdev.hard_start_xmit = ircc_hard_xmit;
+ idev->netdev.open = ircc_net_open;
+ idev->netdev.stop = ircc_net_close;
+
+ irport_start(idev, iobase2);
+
+ /* Open the IrDA device */
+ irda_device_open( idev, driver_name, self);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+
+/*

+ * Function ircc_close (idev)
+ *
+ * Close driver instance
+ *
+ */
+static int ircc_close( struct irda_device *idev)
+{
+ int iobase;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ iobase = idev->io.iobase;
+
+ irport_stop(idev, idev->io.iobase2);
+
+ register_bank(iobase, 0);
+ serial_out(iobase, UART_IER, 0);
+ serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+
+ register_bank(iobase, 1);
+
+ serial_out(iobase, UART_SCE_CFGA,
+ UART_CFGA_IRDA_SIR_A | UART_CFGA_TX_POLARITY);
+ serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
+
+ /* Release the PORT that this driver is using */
+ DEBUG( ircc_debug,
+ __FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase);
+
+ release_region( idev->io.iobase, idev->io.io_ext);
+
+ if ( idev->io.iobase2) {
+ DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n",
+ idev->io.iobase2);
+ release_region( idev->io.iobase2, idev->io.io_ext2);
+ }
+
+ irda_device_close( idev);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+
+/*

+ * Function ircc_probe (iobase, board_addr, irq, dma)
+ *
+ * Returns non-negative on success.
+ *
+ */
+static int ircc_probe( int iobase, int iobase2)
+{
+ int version = 1;
+ int low, high, chip, config, dma, irq;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ register_bank(iobase, 3);
+ high = serial_in(iobase, UART_ID_HIGH);
+ low = serial_in(iobase, UART_ID_LOW);
+ chip = serial_in(iobase, UART_CHIP_ID);
+ version = serial_in(iobase, UART_VERSION);
+ config = serial_in(iobase, UART_INTERFACE);
+ irq = config >> 4 & 0x0f;
+ dma = config & 0x0f;
+
+ if (high == 0x10 && low == 0xb8 && chip == 0xf1) {
+ DEBUG(0, "SMC IrDA Controller found; version = %d, "
+ "port 0x%04x, dma %d, interrupt %d\n",
+ version, iobase, dma, irq);
+ } else {


+ return -1;
+ }
+

+ serial_out(iobase, UART_MASTER, 0);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+
+ return config;
+}
+
+/*
+ * Function ircc_change_speed (idev, baud)
+ *
+ * Change the speed of the device
+ *
+ */
+static void ircc_change_speed( struct irda_device *idev, int speed)
+{
+ struct ircc_cb *self;
+ int iobase, ir_mode, select, fast;
+
+ DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+
+ ASSERT(idev != NULL, return;);
+ ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = idev->priv;
+ iobase = idev->io.iobase;
+
+ /* Update accounting for new speed */
+ idev->io.baudrate = speed;
+
+ switch ( speed) {
+ case 9600:
+ case 19200:
+ case 37600:
+ case 57600:
+ case 115200:
+ DEBUG(ircc_debug+1,
+ __FUNCTION__ ": using irport to change speed to %d\n",
+ speed);
+ register_bank(iobase, 0);
+ serial_out(iobase, UART_IER, 0);
+ serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+ serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+ irport_start(idev, idev->io.iobase2);
+ irport_change_speed( idev, speed);
+ return;
+ break;
+
+ case 576000:
+ ir_mode = UART_CFGA_IRDA_HDLC;
+ select = 0;
+ fast = 0;
+ DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+ break;
+ case 1152000:
+ ir_mode = UART_CFGA_IRDA_HDLC;
+ select = UART_1152;
+ fast = 0;
+ DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+ break;
+ case 4000000:
+ ir_mode = UART_CFGA_IRDA_4PPM;
+ select = 0;
+ fast = UART_LCR_A_FAST;
+ DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
+ return;
+ }
+
+#if 0
+ serial_out(idev->io.iobase2, 4, 0x08);
+#endif
+
+ serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+
+ register_bank(iobase, 0);
+ serial_out(iobase, UART_IER, 0);
+
+ irport_stop(idev, idev->io.iobase2);
+
+ idev->netdev.tbusy = 0;
+
+ register_bank(iobase, 1);
+
+ serial_out(iobase, UART_SCE_CFGA,
+ ((serial_in(iobase, UART_SCE_CFGA) & 0x87) | ir_mode));
+
+ serial_out(iobase, UART_SCE_CFGB,
+ ((serial_in(iobase, UART_SCE_CFGB) & 0x3f) | UART_CFGB_IR));
+
+ (void) serial_in(iobase, UART_FIFO_THRESHOLD);
+ serial_out(iobase, UART_FIFO_THRESHOLD, 64);
+
+ register_bank(iobase, 4);
+
+ serial_out(iobase, UART_CONTROL,
+ (serial_in(iobase, UART_CONTROL) & 0x30)
+ | select | UART_CRC );
+
+ register_bank(iobase, 0);
+
+ serial_out(iobase, UART_LCR_A, fast);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+}
+
+/*
+ * Function ircc_hard_xmit (skb, dev)
+ *
+ * Transmit the frame!
+ *
+ */
+static int ircc_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ int mtt;
+
+ DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+
+ /* Use irport for SIR speeds */
+ if (idev->io.baudrate <= 115200) {
+ DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n");
+ return irport_hard_xmit(skb, dev);
+ }
+
+ DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
+
+ /* Lock transmit buffer */
+ if (irda_lock((void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ memcpy( idev->tx_buff.head, skb->data, skb->len);
+
+ /* Make sure that the length is a multiple of 16 bits */
+ if ( skb->len & 0x01)
+ skb->len++;
+
+ idev->tx_buff.len = skb->len;
+ idev->tx_buff.data = idev->tx_buff.head;
+#if 0
+ idev->tx_buff.offset = 0;
+#endif
+
+ mtt = irda_get_mtt( skb);
+
+ /* Use udelay for delays less than 50 us. */
+ if (mtt)
+ udelay( mtt);
+
+ ircc_dma_write( idev, iobase);
+
+ dev_kfree_skb( skb);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+
+/*

+ * Function ircc_dma_xmit (idev, iobase)
+ *
+ * Transmit data using DMA
+ *
+ */
+static void ircc_dma_write( struct irda_device *idev, int iobase)
+{
+ struct ircc_cb *self;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = idev->priv;
+ iobase = idev->io.iobase;
+
+ setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len,
+ DMA_MODE_WRITE);
+
+ idev->io.direction = IO_XMIT;
+
+ serial_out(idev->io.iobase2, 4, 0x08);
+
+ register_bank(iobase, 4);
+ serial_out(iobase, UART_CONTROL,
+ (serial_in(iobase, UART_CONTROL) & 0xF0));
+
+ serial_out(iobase, UART_BOF_COUNT_LO, 2);
+ serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
+#if 1
+ serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, idev->tx_buff.len >> 8);
+ serial_out(iobase, UART_TX_SIZE_LO, idev->tx_buff.len & 0xff);
+#else
+ serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
+ serial_out(iobase, UART_TX_SIZE_LO, 0);
+#endif
+
+ register_bank(iobase, 1);
+ serial_out(iobase, UART_SCE_CFGB,
+ serial_in(iobase, UART_SCE_CFGB) | UART_CFGB_DMA_ENABLE);
+
+ register_bank(iobase, 0);
+
+ serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME | UART_IER_EOM);
+ serial_out(iobase, UART_LCR_B,
+ UART_LCR_B_SCE_TRANSMIT|UART_LCR_B_SIP_ENABLE);
+
+ serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+}
+
+/*
+ * Function ircc_dma_xmit_complete (idev)
+ *
+ * The transfer of a frame in finished. This function will only be called
+ * by the interrupt handler
+ *
+ */
+static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun)
+{
+ struct ircc_cb *self;
+ int iobase, d;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ register_bank(idev->io.iobase, 1);
+
+ serial_out(idev->io.iobase, UART_SCE_CFGB,
+ serial_in(idev->io.iobase, UART_SCE_CFGB) &
+ ~UART_CFGB_DMA_ENABLE);
+
+ d = get_dma_residue(idev->io.dma);
+
+ DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n",
+ d, idev->tx_buff.len, idev->tx_buff.len - d);
+
+ self = idev->priv;
+
+ iobase = idev->io.iobase;
+
+ /* Check for underrrun! */
+ if ( underrun) {
+ idev->stats.tx_errors++;
+ idev->stats.tx_fifo_errors++;
+ } else {
+ idev->stats.tx_packets++;
+ idev->stats.tx_bytes += idev->tx_buff.len;
+ }
+
+ /* Unlock tx_buff and request another frame */
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->media_busy = FALSE;
+
+ /* Tell the network layer, that we can accept more frames */
+ mark_bh( NET_BH);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+}
+
+/*
+ * Function ircc_dma_receive (idev)
+ *
+ * Get ready for receiving a frame. The device will initiate a DMA
+ * if it starts to receive a frame.
+ *
+ */
+static int ircc_dma_receive( struct irda_device *idev)
+{
+ struct ircc_cb *self;
+ int iobase;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ self = idev->priv;
+ iobase= idev->io.iobase;
+
+ setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize,
+ DMA_MODE_READ);
+
+ /* driver->media_busy = FALSE; */
+ idev->io.direction = IO_RECV;
+ idev->rx_buff.data = idev->rx_buff.head;
+#if 0
+ idev->rx_buff.offset = 0;
+#endif
+
+ register_bank(iobase, 4);
+ serial_out(iobase, UART_CONTROL,
+ (serial_in(iobase, UART_CONTROL) &0xF0));
+ serial_out(iobase, UART_BOF_COUNT_LO, 2);
+ serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
+ serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
+ serial_out(iobase, UART_TX_SIZE_LO, 0);
+ serial_out(iobase, UART_RX_SIZE_HI, 0);
+ serial_out(iobase, UART_RX_SIZE_LO, 0);
+
+ register_bank(iobase, 0);
+ serial_out(iobase,
+ UART_LCR_B, UART_LCR_B_SCE_RECEIVE | UART_LCR_B_SIP_ENABLE);
+
+ register_bank(iobase, 1);
+ serial_out(iobase, UART_SCE_CFGB,
+ serial_in(iobase, UART_SCE_CFGB) |
+ UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+
+/*

+ * Function ircc_dma_receive_complete (idev)
+ *
+ * Finished with receiving frames
+ *
+ *
+ */
+static int ircc_dma_receive_complete( struct irda_device *idev, int iobase)


+{
+ struct sk_buff *skb;

+ struct ircc_cb *self;
+ int len, msgcnt;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ self = idev->priv;
+
+ msgcnt = serial_in(idev->io.iobase, UART_LCR_B) & 0x08;
+
+ DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
+ get_dma_residue(idev->io.dma));
+
+ len = idev->rx_buff.truesize - get_dma_residue(idev->io.dma) - 4;
+
+ DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+
+ skb = dev_alloc_skb( len+1);


+
+ if (skb == NULL) {

+ printk( KERN_INFO __FUNCTION__
+ ": memory squeeze, dropping frame.\n");
+ return FALSE;
+ }
+
+ /* Make sure IP header gets aligned */
+ skb_reserve( skb, 1);
+ skb_put( skb, len);
+
+ memcpy(skb->data, idev->rx_buff.data, len);
+ idev->stats.rx_packets++;
+
+ skb->dev = &idev->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx( skb);
+
+ register_bank(idev->io.iobase, 1);
+ serial_out(idev->io.iobase, UART_SCE_CFGB,
+ serial_in(idev->io.iobase, UART_SCE_CFGB) &
+ ~UART_CFGB_DMA_ENABLE);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ return TRUE;
+}
+
+/*
+ * Function ircc_interrupt (irq, dev_id, regs)
+ *
+ * An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int iobase, iir;
+
+ struct irda_device *idev = (struct irda_device *) dev_id;
+
+ DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+
+ if (idev == NULL) {
+ printk( KERN_WARNING "%s: irq %d for unknown device.\n",
+ driver_name, irq);
+ return;
+ }
+
+ if (idev->io.baudrate <= 115200) {
+ DEBUG(ircc_debug+1, __FUNCTION__
+ ": routing interrupt to irport_interrupt\n");
+ return irport_interrupt( irq, dev_id, regs);
+ }
+
+ iobase = idev->io.iobase;
+
+ idev->netdev.interrupt = 1;
+
+ serial_out(iobase, UART_MASTER, 0);
+
+ register_bank(iobase, 0);
+
+ iir = serial_in(iobase, UART_IIR);
+
+ serial_out(iobase, UART_IER, 0);
+
+ DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
+
+ if (iir & UART_IIR_EOM) {
+ DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
+ if (idev->io.direction == IO_RECV) {
+ ircc_dma_receive_complete(idev, iobase);
+ } else {
+ ircc_dma_xmit_complete(idev, iobase);
+ }
+ ircc_dma_receive(idev);
+ }
+
+ if (iir & UART_IIR_ACTIVE_FRAME) {
+ DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
+ idev->rx_buff.state = INSIDE_FRAME;
+#if 0
+ ircc_dma_receive(idev);
+#endif
+ }
+
+ if (iir & UART_IIR_RAW_MODE) {
+ DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
+ }
+
+ idev->netdev.interrupt = 0;
+
+ register_bank(iobase, 0);
+ serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM);
+ serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+}
+
+/*
+ * Function ircc_wait_until_sent (idev)
+ *
+ * This function should put the current thread to sleep until all data
+ * have been sent, so it is safe to change the speed.
+ */
+static void ircc_wait_until_sent( struct irda_device *idev)
+{
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ /* Just delay 60 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(6);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+}
+
+/*
+ * Function ircc_is_receiving (idev)
+ *
+ * Return TRUE is we are currently receiving a frame
+ *
+ */
+static int ircc_is_receiving( struct irda_device *idev)
+{
+ int status = FALSE;
+ /* int iobase; */
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ ASSERT( idev != NULL, return FALSE;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+ DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
+ get_dma_residue(idev->io.dma));
+
+ status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+
+ return status;
+}
+
+/*
+ * Function ircc_net_init (dev)
+ *
+ * Initialize network device
+ *
+ */
+static int ircc_net_init( struct device *dev)
+{
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ /* Setup to be a normal IrDA network device driver */
+ irda_device_setup( dev);
+
+ /* Insert overrides below this line! */
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+
+

+/*
+ * Function ircc_net_open (dev)
+ *
+ * Start the device
+ *
+ */
+static int ircc_net_open( struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+
+ DEBUG(ircc_debug, __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;);
+
+ iobase = idev->io.iobase;
+
+ if (request_irq( idev->io.irq, ircc_interrupt, 0, idev->name,
+ (void *) idev)) {
+ return -EAGAIN;
+ }
+ /*
+ * Always allocate the DMA channel after the IRQ,
+ * and clean up on failure.
+ */
+ if (request_dma(idev->io.dma, idev->name)) {
+ free_irq( idev->io.irq, idev);
+ return -EAGAIN;
+ }
+
+ /* Ready to play! */


+ dev->tbusy = 0;
+ dev->interrupt = 0;

+ dev->start = 1;
+
+ /* turn on interrupts */
+
+ MOD_INC_USE_COUNT;
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+
+/*

+ * Function ircc_net_close (dev)
+ *
+ * Stop the device
+ *
+ */
+static int ircc_net_close(struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+
+ DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+
+ /* Stop device */


+ dev->tbusy = 1;

+ dev->start = 0;
+

+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ disable_dma( idev->io.dma);
+
+ /* Disable interrupts */
+
+ free_irq( idev->io.irq, idev);
+ free_dma( idev->io.dma);
+
+ MOD_DEC_USE_COUNT;
+
+ DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");


+ return 0;
+}
+

+#ifdef MODULE
+
+MODULE_AUTHOR("Thomas Davis <tad...@jps.net>");
+MODULE_DESCRIPTION("SMC IrCC controller driver");
+MODULE_PARM(ircc_debug,"1i");
+MODULE_PARM(ircc_dma, "1i");
+MODULE_PARM(ircc_irq, "1i");
+
+/*
+ * Function init_module (void)
+ *
+ *
+ *
+ */
+int init_module(void)
+{
+ return ircc_init();
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *
+ *
+ */
+void cleanup_module(void)
+{
+ ircc_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.3.5/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.3.5/linux/drivers/net/irda/tekram.c Mon May 31 22:28:05 1999
+++ linux/drivers/net/irda/tekram.c Mon Jun 7 16:18:58 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X *
X * Filename: tekram.c
- * Version: 1.1
+ * Version: 1.2
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: Mon May 10 16:10:17 1999
+ * Modified at: Sun May 16 14:33:42 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -28,16 +28,12 @@
X #include <linux/sched.h>
X #include <linux/init.h>
X
-#include <asm/ioctls.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
X #include <net/irda/irda.h>
X #include <net/irda/irda_device.h>
X #include <net/irda/irtty.h>
X #include <net/irda/dongle.h>
X
-static void tekram_reset(struct irda_device *dev, int unused);
+static void tekram_reset(struct irda_device *dev);
X static void tekram_open(struct irda_device *dev, int type);
X static void tekram_close(struct irda_device *dev);
X static void tekram_change_speed(struct irda_device *dev, int baud);
@@ -49,7 +45,7 @@
X #define TEKRAM_19200 0x03
X #define TEKRAM_9600 0x04
X
-#define TEKRAM_PW 0x10 /* Pulse select bit */
+#define TEKRAM_PW 0x10 /* Pulse select bit */
X
X static struct dongle dongle = {
X TEKRAM_DONGLE,
@@ -112,7 +108,7 @@
X
X ASSERT(idev != NULL, return;);
X ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
+
X switch (baud) {
X default:
X case 9600:
@@ -121,7 +117,7 @@
X case 19200:
X byte = TEKRAM_PW|TEKRAM_19200;
X break;
- case 34800:
+ case 38400:
X byte = TEKRAM_PW|TEKRAM_38400;
X break;
X case 57600:
@@ -132,6 +128,9 @@
X break;
X }
X
+ /* Need to reset the dongle and go to 9600 bps before programming */
+ tekram_reset(idev);
+
X /* Set DTR, Clear RTS */
X irda_device_set_dtr_rts(idev, TRUE, FALSE);
X
@@ -162,7 +161,7 @@
X * 3. clear DTR to SPACE state, wait at least 50 us for further
X * operation
X */
-void tekram_reset(struct irda_device *idev, int unused)
+void tekram_reset(struct irda_device *idev)
X {
X ASSERT(idev != NULL, return;);
X ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -185,8 +184,10 @@
X irda_device_set_dtr_rts(idev, TRUE, TRUE);
X
X udelay(50);
-
- /* Finished! */
+
+ /* Make sure the IrDA chip also goes to defalt speed */
+ if (idev->change_speed)
+ idev->change_speed(idev, 9600);
X }
X
X /*
diff -u --recursive --new-file v2.3.5/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.3.5/linux/drivers/net/irda/uircc.c Mon May 31 22:28:06 1999
+++ linux/drivers/net/irda/uircc.c Mon Jun 7 16:18:58 1999
@@ -7,7 +7,7 @@
X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sat Dec 26 10:59:03 1998
- * Modified at: Mon May 10 22:11:09 1999
+ * Modified at: Wed May 19 15:29:56 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -216,7 +216,7 @@
X idev->netdev.open = uircc_net_open;
X idev->netdev.stop = uircc_net_close;
X
- irport_start(iobase2);
+ irport_start(idev, iobase2);
X
X /* Open the IrDA device */
X irda_device_open(idev, driver_name, self);
@@ -251,7 +251,7 @@
X /* Disable modem */
X outb(0x00, iobase+UIRCC_CR10);
X
- irport_stop(idev->io.iobase2);
+ irport_stop(idev, idev->io.iobase2);
X
X /* Release the PORT that this driver is using */
X DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
@@ -350,7 +350,7 @@
X case 37600:
X case 57600:
X case 115200:
- irport_start(idev->io.iobase2);
+ irport_start(idev, idev->io.iobase2);
X irport_change_speed(idev, speed);
X
X /* Some magic to disable FIR and enable SIR */
@@ -367,7 +367,7 @@
X DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
X break;
X case 4000000:
- irport_stop(idev->io.iobase2);
+ irport_stop(idev, 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.5/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.5/linux/drivers/net/irda/w83977af_ir.c Mon May 31 22:28:06 1999
+++ linux/drivers/net/irda/w83977af_ir.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@
X * Status: Experimental.
X * Author: Paul VanderSpek
X * Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Thu May 13 08:03:27 1999
+ * Modified at: Fri May 21 22:18:19 1999
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>
@@ -80,8 +80,6 @@
X
X static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
X
-static struct st_fifo_entry prev;
-
X /* Some prototypes */
X static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
X unsigned int dma);
@@ -112,8 +110,6 @@
X int i;
X
X DEBUG(0, __FUNCTION__ "()\n");
-
- prev.status = 0;
X
X for (i=0; (io[i] < 2000) && (i < 4); i++) {
X int ioaddr = io[i];
diff -u --recursive --new-file v2.3.5/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.3.5/linux/drivers/net/myri_sbus.c Fri Mar 26 13:57:41 1999
+++ linux/drivers/net/myri_sbus.c Wed Jun 9 14:45:36 1999
@@ -756,6 +756,7 @@
X eth->h_proto = type;
X memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
X memcpy(eth->h_dest, neigh->ha, dev->addr_len);
+ hh->hh_len = 16;


X return 0;
X }
X

diff -u --recursive --new-file v2.3.5/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.3.5/linux/drivers/net/ni52.c Wed Oct 7 15:51:45 1998
+++ linux/drivers/net/ni52.c Tue Jun 8 10:27:18 1999
@@ -5,7 +5,7 @@
X * same Gnu Public License that covers that work.
X *
X * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later)
- * Copyrights (c) 1994,1995,1996 by M.Hipp (Michae...@student.uni-tuebingen.de)
+ * Copyrights (c) 1994,1995,1996 by M.Hipp (hi...@informatik.uni-tuebingen.de)
X * [feel free to mail ....]
X *
X * when using as module: (no autoprobing!)
diff -u --recursive --new-file v2.3.5/linux/drivers/net/ni52.h linux/drivers/net/ni52.h
--- v2.3.5/linux/drivers/net/ni52.h Thu Apr 11 23:49:38 1996
+++ linux/drivers/net/ni52.h Tue Jun 8 10:27:18 1999
@@ -4,7 +4,7 @@
X * This is an extension to the Linux operating system, and is covered by the
X * same Gnu Public License that covers that work.
X *
- * copyrights (c) 1994 by Michael Hipp (mh...@student.uni-tuebingen.de)
+ * copyrights (c) 1994 by Michael Hipp (hi...@informatik.uni-tuebingen.de)
X *
X * I have done a look in the following sources:
X * crynwr-packet-driver by Russ Nelson
diff -u --recursive --new-file v2.3.5/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.3.5/linux/drivers/net/ni65.c Fri Oct 9 11:56:59 1998
+++ linux/drivers/net/ni65.c Tue Jun 8 10:27:18 1999
@@ -16,7 +16,7 @@
X *
X * comments/bugs/suggestions can be sent to:
X * Michael Hipp
- * email: Michae...@student.uni-tuebingen.de
+ * email: hi...@informatik.uni-tuebingen.de
X *
X * sources:
X * some things are from the 'ni6510-packet-driver for dos by Russ Nelson'
@@ -45,6 +45,7 @@
X */
X
X /*
+ * 99.Jun.8: added support for /proc/net/dev byte count for xosview (HK)
X * 96.Sept.29: virt_to_bus stuff added for new memory modell
X * 96.April.29: Added Harald Koenig's Patches (MH)
X * 96.April.13: enhanced error handling .. more tests (MH)
@@ -966,8 +967,10 @@
X p->stats.tx_errors++;
X tmdp->status2 = 0;
X }
- else
+ else {
+ p->stats.tx_bytes -= (short)(tmdp->blen);
X p->stats.tx_packets++;
+ }
X
X #ifdef XMT_VIA_SKB
X if(p->tmd_skb[p->tmdlast]) {
@@ -1054,6 +1057,7 @@
X eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
X #endif
X p->stats.rx_packets++;
+ p->stats.rx_bytes += len;
X skb->protocol=eth_type_trans(skb,dev);
X netif_rx(skb);
X }
diff -u --recursive --new-file v2.3.5/linux/drivers/net/ptifddi.c linux/drivers/net/ptifddi.c
--- v2.3.5/linux/drivers/net/ptifddi.c Wed Jun 2 14:44:39 1999
+++ linux/drivers/net/ptifddi.c Wed Jun 9 14:45:36 1999
@@ -1,4 +1,4 @@
-/* $Id: ptifddi.c,v 1.5 1997/04/16 10:27:27 jj Exp $
+/* $Id: ptifddi.c,v 1.7 1999/06/09 08:19:01 davem Exp $
X * ptifddi.c: Network driver for Performance Technologies single-attach
X * and dual-attach FDDI sbus cards.
X *
diff -u --recursive --new-file v2.3.5/linux/drivers/net/sdladrv.c linux/drivers/net/sdladrv.c
--- v2.3.5/linux/drivers/net/sdladrv.c Thu Jan 7 09:21:53 1999
+++ linux/drivers/net/sdladrv.c Wed Jun 2 14:40:22 1999
@@ -13,6 +13,7 @@
X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X * ============================================================================
+* May 19, 1999 Arnaldo Melo wanpipe_init belongs to sdlamain.c
X * Dec 20, 1996 Gene Kozin Version 3.0.0. Complete overhaul.
X * Jul 12, 1996 Gene Kozin Changes for Linux 2.0 compatibility.
X * Jun 12, 1996 Gene Kozin Added support for S503 card.
@@ -89,7 +90,6 @@
X #include <linux/sched.h> /* for jiffies, HZ, etc. */
X #include <linux/sdladrv.h> /* API definitions */
X #include <linux/sdlasfm.h> /* SDLA firmware module definitions */
-#include <linux/init.h>
X #include <asm/io.h> /* for inb(), outb(), etc. */
X #define _INB(port) (inb(port))
X #define _OUTB(port, byte) (outb((byte),(port)))
@@ -288,9 +288,6 @@
X

X #ifdef MODULE
X int init_module (void)

-#else
-__initfunc(int wanpipe_init(void))
-#endif
X {
X printk(KERN_INFO "%s v%u.%u %s\n",
X fullname, MOD_VERSION, MOD_RELEASE, copyright);
@@ -301,7 +298,6 @@


X return 0;
X }
X

-#ifdef MODULE
X /*============================================================================
X * Module 'remove' entry point.
X * o release all remaining system resources
diff -u --recursive --new-file v2.3.5/linux/drivers/net/sdlamain.c linux/drivers/net/sdlamain.c
--- v2.3.5/linux/drivers/net/sdlamain.c Mon Dec 28 11:05:14 1998
+++ linux/drivers/net/sdlamain.c Wed Jun 2 14:40:22 1999
@@ -11,6 +11,7 @@
X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X * ============================================================================
+* May 19, 1999 Arnaldo Melo __initfunc for wanpipe_init
X * Nov 28, 1997 Jaspreet Singh Changed DRV_RELEASE to 1
X * Nov 10, 1997 Jaspreet Singh Changed sti() to restore_flags();
X * Nov 06, 1997 Jaspreet Singh Changed DRV_VERSION to 4 and DRV_RELEASE to 0
@@ -42,6 +43,7 @@
X #include <linux/wanpipe.h> /* WANPIPE common user API definitions */
X #include <asm/uaccess.h> /* kernel <-> user copy */
X #include <asm/io.h> /* phys_to_virt() */
+#include <linux/init.h> /* __initfunc (when not using as a module) */
X
X
X /****** Defines & Macros ****************************************************/
@@ -122,7 +124,7 @@


X #ifdef MODULE
X int init_module (void)
X #else

-int wanpipe_init(void)
+__initfunc(int wanpipe_init(void))
X #endif
X {
X int cnt, err = 0;
diff -u --recursive --new-file v2.3.5/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- v2.3.5/linux/drivers/net/sk_mca.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/sk_mca.c Mon Jun 7 14:34:46 1999
@@ -0,0 +1,1143 @@
+/*
+net-3-driver for the SKNET MCA-based cards
+
+This is an extension to the Linux operating system, and is covered by the
+same Gnu Public License that covers that work.
+
+Copyright 1999 by Alfred Arnold (alf...@ccac.rwth-aachen.de, aar...@elsa.de)
+
+This driver is based both on the 3C523 driver and the SK_G16 driver.
+
+paper sources:
+ 'PC Hardware: Aufbau, Funktionsweise, Programmierung' by
+ Hans-Peter Messmer for the basic Microchannel stuff
+
+ 'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer
+ for help on Ethernet driver programming
+
+ 'Ethernet/IEEE 802.3 Family 1992 World Network Data Book/Handbook' by AMD
+ for documentation on the AM7990 LANCE
+
+ 'SKNET Personal Technisches Manual', Version 1.2 by Schneider&Koch
+ for documentation on the Junior board
+
+ 'SK-NET MC2+ Technical Manual", Version 1.1 by Schneider&Koch for
+ documentation on the MC2 bord
+
+ A big thank you to the S&K support for providing me so quickly with
+ documentation!
+
+ Also see http://www.syskonnect.com/
+
+ Missing things:
+
+ -> set debug level via ioctl instead of compile-time switches
+ -> I didn't follow the development of the 2.1.x kernels, so my
+ assumptions about which things changed with which kernel version
+ are probably nonsense
+
+History:
+ May 16th, 1999
+ startup
+ May 22st, 1999
+ added private structure, methods
+ begun building data structures in RAM
+ May 23nd, 1999
+ can receive frames, send frames
+ May 24th, 1999
+ modularized intialization of LANCE
+ loadable as module
+ still Tx problem :-(
+ May 26th, 1999
+ MC2 works
+ support for multiple devices
+ display media type for MC2+
+ May 28th, 1999
+ fixed problem in GetLANCE leaving interrupts turned off
+ increase TX queue to 4 packets to improve send performance
+ May 29th, 1999
+ a few corrections in statistics, caught rcvr overruns
+ reinitialization of LANCE/board in critical situations
+ MCA info implemented
+ implemented LANCE multicast filter
+ Jun 6th, 1999
+ additions for Linux 2.2
+
+ *************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/mca.h>
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif


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

echo 'End of part 10'
echo 'File patch-2.3.6 is continued in part 11'
echo 11 > _shar_seq_.tmp
exit 0

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part14

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


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

if test "$Scheck" != 14; then


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

+ if (sc->device_flags[i] & CFSYNCHISULTRA)
+ {
+ p->ultraenb |= mask;
+ }
X }
X else if (sc->adapter_control & CFULTRAEN)
X {
@@ -8364,18 +8829,54 @@
X p->ultraenb &= ~mask;
X p->transinfo[i].user_offset = 0;
X p->transinfo[i].user_period = 0;
+ p->transinfo[i].user_options = 0;
X p->transinfo[i].cur_offset = 0;
X p->transinfo[i].cur_period = 0;
+ p->transinfo[i].cur_options = 0;


X p->needsdtr_copy &= ~mask;
X }

X else
X {


- if (p->features & AHC_ULTRA2)
+ if (p->features & AHC_ULTRA3)

+ {
+ p->transinfo[i].user_offset = MAX_OFFSET_ULTRA2;
+ p->transinfo[i].cur_offset = aic_inb(p, TARG_OFFSET + i);
+ if( (sc->device_flags[i] & CFXFER) < 0x03 )
+ {
+ scsirate = (sc->device_flags[i] & CFXFER);
+ p->transinfo[i].user_options = MSG_EXT_PPR_OPTION_DT_CRC;
+ if( (aic_inb(p, TARG_SCSIRATE + i) & CFXFER) < 0x03 )
+ {
+ p->transinfo[i].cur_options =
+ ((aic_inb(p, TARG_SCSIRATE + i) & 0x40) ?
+ MSG_EXT_PPR_OPTION_DT_CRC : MSG_EXT_PPR_OPTION_DT_UNITS);
+ }
+ else
+ {
+ p->transinfo[i].cur_options = 0;


+ }
+ }
+ else
+ {

+ scsirate = (sc->device_flags[i] & CFXFER) |
+ ((p->ultraenb & mask) ? 0x18 : 0x10);
+ p->transinfo[i].user_options = 0;
+ p->transinfo[i].cur_options = 0;
+ }
+ p->transinfo[i].user_period = aic7xxx_find_period(p, scsirate,
+ AHC_SYNCRATE_ULTRA3);
+ p->transinfo[i].cur_period = aic7xxx_find_period(p,
+ aic_inb(p, TARG_SCSIRATE + i),
+ AHC_SYNCRATE_ULTRA3);
+ }
+ else if (p->features & AHC_ULTRA2)
X {
X p->transinfo[i].user_offset = MAX_OFFSET_ULTRA2;
X p->transinfo[i].cur_offset = aic_inb(p, TARG_OFFSET + i);
X scsirate = (sc->device_flags[i] & CFXFER) |
X ((p->ultraenb & mask) ? 0x18 : 0x10);
+ p->transinfo[i].user_options = 0;
+ p->transinfo[i].cur_options = 0;
X p->transinfo[i].user_period = aic7xxx_find_period(p, scsirate,
X AHC_SYNCRATE_ULTRA2);
X p->transinfo[i].cur_period = aic7xxx_find_period(p,
@@ -8385,10 +8886,9 @@
X else
X {
X scsirate = (sc->device_flags[i] & CFXFER) << 4;
- if (sc->device_flags[i] & CFWIDEB)
- p->transinfo[i].user_offset = MAX_OFFSET_16BIT;
- else
- p->transinfo[i].user_offset = MAX_OFFSET_8BIT;
+ p->transinfo[i].user_options = 0;
+ p->transinfo[i].cur_options = 0;
+ p->transinfo[i].user_offset = MAX_OFFSET_8BIT;
X if (p->features & AHC_ULTRA)
X {
X short ultraenb;
@@ -8427,9 +8927,10 @@
X }
X aic_outb(p, ~(p->discenable & 0xFF), DISC_DSB);
X aic_outb(p, ~((p->discenable >> 8) & 0xFF), DISC_DSB + 1);
+ p->needppr = p->needppr_copy = p->needdv = 0;
X p->needwdtr = p->needwdtr_copy;
X p->needsdtr = p->needsdtr_copy;
- p->wdtr_pending = p->sdtr_pending = 0;
+ p->dtr_pending = 0;
X
X /*
X * We set the p->ultraenb from the SEEPROM to begin with, but now we make
@@ -8453,6 +8954,7 @@
X {
X case AHC_AIC7895:
X case AHC_AIC7896:
+ case AHC_AIC7899:
X if (p->adapter_control & CFBPRIMARY)
X p->flags |= AHC_CHANNEL_B_PRIMARY;
X default:
@@ -8783,6 +9285,14 @@
X {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7855, AHC_AIC7850,
X AHC_PAGESCBS, AHC_AIC7850_FE, 6,
X 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7821, AHC_AIC7860,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7860_FE, 7,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_3860, AHC_AIC7860,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7860_FE, 7,
+ 32, C46 },
X {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X AHC_AIC7860_FE, 7,
@@ -8825,6 +9335,18 @@
X {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7884, AHC_AIC7880,
X AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
X 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7885, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7886, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
X {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
X AHC_AIC7895_FE, 19,
@@ -8833,30 +9355,66 @@
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X AHC_AIC7890_FE, 20,
X 32, C46 },
- {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_78902, AHC_AIC7890,
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X AHC_AIC7890_FE, 20,
X 32, C46 },
- {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
X AHC_AIC7890_FE, 21,
X 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7890_FE, 22,
+ 32, C46 },
X {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 22,
+ AHC_AIC7896_FE, 23,
X 32, C56_66 },
X {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 23,
+ AHC_AIC7896_FE, 24,
X 32, C56_66 },
X {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 24,
+ AHC_AIC7896_FE, 25,
X 32, C56_66 },
X {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
X AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7860_FE, 25,
+ AHC_AIC7860_FE, 26,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
X 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
X };
X
X unsigned short command;
@@ -8926,11 +9484,11 @@
X }
X #ifdef AIC7XXX_STRICT_PCI_SETUP
X command |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
- PCI_COMMAND_INVALIDATE | PCI_COMMAND_MASTER |
- PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #else
X command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #endif
+ command &= ~PCI_COMMAND_INVALIDATE;
X if (aic7xxx_pci_parity == 0)
X command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
X pci_write_config_word(pdev, PCI_COMMAND, command);
@@ -8940,15 +9498,7 @@
X {
X printk("aic7xxx: Initial DEVCONFIG value was 0x%x\n", devconfig);
X }
- devconfig |= 0x80000000;
- if ((aic7xxx_pci_parity == 0) || (aic7xxx_pci_parity == -1))
- {
- devconfig &= ~(0x00000008);
- }
- else
- {
- devconfig |= 0x00000008;
- }
+ devconfig |= 0x80000040;
X pci_write_config_dword(pdev, DEVCONFIG, devconfig);
X #endif /* AIC7XXX_STRICT_PCI_SETUP */
X #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
@@ -8976,11 +9526,11 @@
X }
X #ifdef AIC7XXX_STRICT_PCI_SETUP
X command |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
- PCI_COMMAND_INVALIDATE | PCI_COMMAND_MASTER |
- PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #else
X command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
X #endif
+ command &= ~PCI_COMMAND_INVALIDATE;
X if (aic7xxx_pci_parity == 0)
X command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
X pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, command);
@@ -8990,15 +9540,7 @@
X {
X printk("aic7xxx: Initial DEVCONFIG value was 0x%x\n", devconfig);
X }
- devconfig |= 0x80000000;
- if ((aic7xxx_pci_parity == 0) || (aic7xxx_pci_parity == -1))
- {
- devconfig &= ~(0x00000008);
- }
- else
- {
- devconfig |= 0x00000008;
- }
+ devconfig |= 0x80000040;
X pcibios_write_config_dword(pci_bus, pci_devfn, DEVCONFIG, devconfig);
X #endif /* AIC7XXX_STRICT_PCI_SETUP */
X #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
@@ -9137,6 +9679,7 @@
X
X case AHC_AIC7895: /* 7895 */
X case AHC_AIC7896: /* 7896/7 */
+ case AHC_AIC7899: /* 7899 */
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X if (PCI_FUNC(temp_p->pdev->devfn) != 0)
X {
@@ -9185,43 +9728,38 @@
X */
X switch (temp_p->chip & AHC_CHIPID_MASK)
X {
- case AHC_AIC7890:
- case AHC_AIC7896:
+ case AHC_AIC7892:
+ case AHC_AIC7899:
X aic_outb(temp_p, 0, SCAMCTL);
X /*
- * We used to set DPARCKEN in this register, but after talking
- * to a tech from Adaptec, I found out they don't use that
- * particular bit in their own register settings, and when you
- * combine that with the fact that I determined that we were
- * seeing Data-Path Parity Errors on things we shouldn't see
- * them on, I think there is a bug in the silicon and the way
- * to work around it is to disable this particular check. Also
- * This bug only showed up on certain commands, so it seems to
- * be pattern related or some such. The commands we would
- * typically send as a linux TEST_UNIT_READY or INQUIRY command
- * could cause it to be triggered, while regular commands that
- * actually made reasonable use of the SG array capabilities
- * seemed not to cause the problem.
+ * Switch to the alt mode of the chip...
+ */
+ aic_outb(temp_p, aic_inb(temp_p, SFUNCT) | ALT_MODE, SFUNCT);
+ /*
+ * Set our options...the last two items set our CRC after x byte
+ * count in target mode...
X */
+ aic_outb(temp_p, AUTO_MSGOUT_DE | DIS_MSGIN_DUALEDGE, OPTIONMODE);
+ aic_outb(temp_p, 0x00, 0x0b);
+ aic_outb(temp_p, 0x10, 0x0a);
X /*
- aic_outb(temp_p, aic_inb(temp_p, DSCOMMAND0) |
- CACHETHEN | DPARCKEN | MPARCKEN |
- USCBSIZE32 | CIOPARCKEN,
- DSCOMMAND0);
+ * switch back to normal mode...
X */
+ aic_outb(temp_p, aic_inb(temp_p, SFUNCT) & ~ALT_MODE, SFUNCT);
+ aic_outb(temp_p, CRCVALCHKEN | CRCENDCHKEN | CRCREQCHKEN |
+ TARGCRCENDEN | TARGCRCCNTEN,
+ CRCCONTROL1);
+ aic_outb(temp_p, ((aic_inb(temp_p, DSCOMMAND0) | USCBSIZE32 |
+ MPARCKEN | CIOPARCKEN | CACHETHEN) &
+ ~DPARCKEN), DSCOMMAND0);
+ aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+ break;
+ case AHC_AIC7890:
+ case AHC_AIC7896:
+ aic_outb(temp_p, 0, SCAMCTL);
X aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
X CACHETHEN | MPARCKEN | USCBSIZE32 |
X CIOPARCKEN) & ~DPARCKEN, DSCOMMAND0);
- /* FALLTHROUGH */
- default:
- /*
- * We attempt to read a SEEPROM on *everything*. If we fail,
- * then we fail, but this covers things like 2910c cards that
- * now have SEEPROMs with their 7856 chipset that we would
- * otherwise ignore. They still don't have a BIOS, but they
- * have a SEEPROM that the SCSISelect utility on the Adaptec
- * diskettes can configure.
- */
X aic7xxx_load_seeprom(temp_p, &sxfrctl1);
X break;
X case AHC_AIC7850:
@@ -9233,14 +9771,13 @@
X aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
X CACHETHEN | MPARCKEN) & ~DPARCKEN,
X DSCOMMAND0);
+ /* FALLTHROUGH */
+ default:
X aic7xxx_load_seeprom(temp_p, &sxfrctl1);
X break;
X case AHC_AIC7880:
X /*
- * Only set the DSCOMMAND0 register if this is a Rev B.
- * chipset. For those, we also enable Ultra mode by
- * force due to brain-damage on the part of some BIOSes
- * We overload the devconfig variable here since we can.
+ * Check the rev of the chipset before we change DSCOMMAND0
X */
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
@@ -9272,6 +9809,7 @@
X {
X case AHC_AIC7895:
X case AHC_AIC7896:
+ case AHC_AIC7899:
X current_p = list_p;
X while(current_p != NULL)
X {
@@ -9315,6 +9853,7 @@
X break;
X case AHC_AIC7895:
X case AHC_AIC7896:
+ case AHC_AIC7899:
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
X pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
X #else
@@ -9364,7 +9903,7 @@
X */
X if (temp_p->features & AHC_ULTRA2)
X {
- aic_outb(temp_p, RD_DFTHRSH_75 | WR_DFTHRSH_75, DFF_THRSH);
+ aic_outb(temp_p, RD_DFTHRSH_MAX | WR_DFTHRSH_MAX, DFF_THRSH);
X }
X else
X {
@@ -9512,7 +10051,7 @@
X }
X }
X /*
- * Are we dealing with a 7985 where we need to sort the
+ * Are we dealing with a 7895/6/7/9 where we need to sort the
X * channels as well, if so, the bios_address values should
X * be the same
X */
@@ -9603,7 +10142,54 @@
X return (found);
X }
X
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
+static void aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p,
+ Scsi_Cmnd *old_cmd, int tindex);


+
+/*+F*************************************************************************
+ * Function:

+ * aic7xxx_allocate_negotiation_command


+ *
+ * Description:

+ * allocate the actual command struct and fill in the gaps...
+ *-F*************************************************************************/
+static Scsi_Cmnd *
+aic7xxx_allocate_negotiation_command(struct aic7xxx_host *p,
+ Scsi_Cmnd *old_cmd, int tindex)
+{
+ Scsi_Cmnd *cmd;
+ char *buffer;
+
+ if (!(p->dev_dtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+ {
+ return(NULL);
+ }
+ if (!(buffer = kmalloc(256, GFP_ATOMIC)))
+ {
+ kfree(p->dev_dtr_cmnd[tindex]);
+ p->dev_dtr_cmnd[tindex] = NULL;
+ return(NULL);
+ }
+ cmd = p->dev_dtr_cmnd[tindex];
+ memset(cmd, 0, sizeof(Scsi_Cmnd));
+ memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
+ memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
+ memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
+ cmd->lun = 0;
+ cmd->request_bufflen = 255;
+ cmd->request_buffer = buffer;
+ cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
+ cmd->bufflen = 0;
+ cmd->buffer = NULL;
+ cmd->underflow = 0;
+ cmd->cmd_len = 6;
+ cmd->cmnd[0] = cmd->data_cmnd[0] = INQUIRY;
+ cmd->cmnd[1] = cmd->data_cmnd[1] = 0;
+ cmd->cmnd[2] = cmd->data_cmnd[2] = 0;
+ cmd->cmnd[3] = cmd->data_cmnd[3] = 0;
+ cmd->cmnd[4] = cmd->data_cmnd[4] = 255; /* match what scsi.c does here */
+ cmd->cmnd[5] = cmd->data_cmnd[5] = 0;
+ return(cmd);
+}


X
X /*+F*************************************************************************
X * Function:

@@ -9616,6 +10202,117 @@
X static void
X aic7xxx_negotiation_complete(Scsi_Cmnd *cmd)
X {
+ unsigned int checksum;
+ int i;
+ int *ibuffer;
+ struct aic7xxx_host *p = (struct aic7xxx_host *)cmd->host->hostdata;
+ int tindex = TARGET_INDEX(cmd);


+ struct aic7xxx_syncrate *syncrate;
+

+ /*
+ * perform our minimalistic domain validation
+ */
+ if(p->dev_flags[tindex] & DEVICE_SCANNED)
+ {
+ ibuffer = (int *)cmd->request_buffer;
+ checksum = 0;
+ for(i = 0; i < (cmd->request_bufflen >> 2); i++)


+ {
+ checksum += ibuffer[i];
+ }

+ if( (checksum != p->dev_checksum[tindex]) &&
+ (p->transinfo[tindex].cur_offset != 0) )
+ {


+ unsigned int period = p->transinfo[tindex].cur_period;
+ unsigned char options = p->transinfo[tindex].cur_options;
+

+ if (p->needdv & (1<<tindex))
+ {


+ /*
+ * oops, we had a failure, lower the transfer rate and try again. It's
+ * worth noting here that it might be wise to also check for typical
+ * wide setting on narrow cable type problems and try disabling wide
+ * instead of slowing down if those exist. That's hard to do with simple
+ * checksums though.
+ */

+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION)
+ {
+ printk(INFO_LEAD "reducing SCSI transfer speed due to Domain "
+ "validation failure.\n", p->host_no, CTL_OF_CMD(cmd));
+ }


+ if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
+ {
+ syncrate++;
+ if( (syncrate->rate[0] != NULL) &&
+ (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
+ {
+ p->transinfo[tindex].goal_period = syncrate->period;
+ if( !(syncrate->sxfr_ultra2 & 0x40) )
+ {
+ p->transinfo[tindex].goal_options = 0;
+ }
+ }
+ else
+ {
+ p->transinfo[tindex].goal_offset = 0;
+ p->transinfo[tindex].goal_period = 0;
+ p->transinfo[tindex].goal_options = 0;
+ }
+ p->needppr |= (p->needppr_copy & (1<<tindex));
+ p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+ p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+ }

+ p->needdv &= ~(1<<tindex);
+ }
+ else
+ {
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION)
+ {
+ printk(INFO_LEAD "Performing Domain validation.\n",
+ p->host_no, CTL_OF_CMD(cmd));
+ }
+ /*
+ * Update the checksum in case the INQUIRY data has changed, maybe
+ * in relation to a change in the mode pages, or whatever.
+ */


+ p->dev_checksum[tindex] = checksum;

+ /*
+ * Signal that we are trying out the domain validation
+ */
+ p->needdv |= (1<<tindex);
+ /*
+ * Signal that we need to re-negotiate things, this also gets us our
+ * INQUIRY command to re-checksum off of.
+ */


+ p->needppr |= (p->needppr_copy & (1<<tindex));
+ p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+ p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+ }
+ }

+ else
+ {
+ if( (aic7xxx_verbose & VERBOSE_NEGOTIATION) &&
+ (p->needdv & (1<<tindex)) )
+ {
+ printk(INFO_LEAD "Successfully completed Domain validation.\n",
+ p->host_no, CTL_OF_CMD(cmd));
+ }
+ /*
+ * We successfully did our checksum, so don't leave the needdv flag set
+ * in case we might have set it last time through.
+ */
+ p->needdv &= ~(1<<tindex);
+ }
+ }
+
+ p->dtr_pending &= ~(0x01 << tindex);
+ /*
+ * This looks recursive in the extreme, but if this was a WDTR negotiation
+ * and we didn't follow up with SDTR yet, then this will get it started.
+ * For all other cases, this should work out to be a no-op, unless we are
+ * doing domain validation and happen to need a new negotiation command.
+ */
+ aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
X return;
X }
X
@@ -9632,81 +10329,63 @@
X int tindex)
X {
X
- if ( (p->needwdtr & (1<<tindex)) && !(p->wdtr_pending & (1<<tindex)) )
+ if ( !(p->dtr_pending & (1<<tindex)) &&
+ ( (p->needppr & (1<<tindex)) ||


+ (p->needwdtr & (1<<tindex)) ||

+ (p->needsdtr & (1<<tindex)) ) )
X {
- if(p->dev_wdtr_cmnd[tindex] == NULL)
+ if ( (p->dev_dtr_cmnd[tindex] == NULL) &&
+ (aic7xxx_allocate_negotiation_command(p, old_cmd, tindex) == NULL) )
X {
- Scsi_Cmnd *cmd;
-
- if (!(p->dev_wdtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
- {
- return;
- }
- cmd = p->dev_wdtr_cmnd[tindex];
- memset(cmd, 0, sizeof(Scsi_Cmnd));
- memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
- memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
- memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
- cmd->lun = 0;
- cmd->request_bufflen = 0;
- cmd->request_buffer = NULL;
- cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
- cmd->bufflen = 0;
- cmd->buffer = NULL;
- cmd->underflow = 0;
- cmd->cmd_len = 6;
+ return;
X }
X /*
- * Before sending this thing out, we also amke the cmd->next pointer
+ * Before sending this thing out, we also make the cmd->next pointer
X * point to the real command so we can stuff any possible SENSE data
- * intp the real command instead of this fake command. This has to be
+ * into the real command instead of this fake command. This has to be
X * done each time the command is built, not just the first time, hence
X * it's outside of the above if()...
X */
- p->dev_wdtr_cmnd[tindex]->next = old_cmd;
- aic7xxx_queue(p->dev_wdtr_cmnd[tindex],
- aic7xxx_negotiation_complete);
- }
- else if ( (p->needsdtr & (1<<tindex)) && !(p->sdtr_pending & (1<<tindex)) &&
- !(p->wdtr_pending & (1<<tindex)) )
- {
- if(p->dev_sdtr_cmnd[tindex] == NULL)
+ p->dev_dtr_cmnd[tindex]->next = old_cmd;
+ /*
+ * Clear the buffer so checksums come out right....
+ */
+ memset(p->dev_dtr_cmnd[tindex]->request_buffer, 0,
+ p->dev_dtr_cmnd[tindex]->request_bufflen);
+ /*
+ * Remove any commands for this particular device that might be on the
+ * waiting_scbs queue or qinfifo so that this command goes out first.
+ * This is vital for our implementation of domain validation.
+ */
+ pause_sequencer(p);
+ aic7xxx_search_qinfifo(p, old_cmd->target, old_cmd->channel, ALL_LUNS,
+ SCB_LIST_NULL, 0, TRUE, &p->delayed_scbs[tindex]);
+ unpause_sequencer(p, FALSE);
X {
- Scsi_Cmnd *cmd;
+ struct aic7xxx_scb *scb, *next;
X
- if (!(p->dev_sdtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+ scb = p->waiting_scbs.head;
+ while(scb != NULL)
X {
- return;
+ if( aic7xxx_match_scb(p, scb, old_cmd->target, old_cmd->channel,
+ ALL_LUNS, SCB_LIST_NULL) )
+ {
+ next = scb->q_next;
+ scbq_remove(&p->waiting_scbs, scb);
+ scbq_insert_tail(&p->delayed_scbs[tindex], scb);
+ scb = next;
+ }
+ else
+ {
+ scb = scb->q_next;
+ }
X }
- cmd = p->dev_sdtr_cmnd[tindex];
- memset(cmd, 0, sizeof(Scsi_Cmnd));
- memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
- memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
- memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
- cmd->lun = 0;
- cmd->request_bufflen = 0;
- cmd->request_buffer = NULL;
- cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
- cmd->bufflen = 0;
- cmd->buffer = NULL;
- cmd->underflow = 0;
- cmd->cmd_len = 6;
X }
- /*
- * Before sending this thing out, we also amke the cmd->next pointer
- * point to the real command so we can stuff any possible SENSE data
- * intp the real command instead of this fake command. This has to be
- * done each time the command is built, not just the first time, hence
- * it's outside of the above if()...
- */
- p->dev_sdtr_cmnd[tindex]->next = old_cmd;
- aic7xxx_queue(p->dev_sdtr_cmnd[tindex],
+ aic7xxx_queue(p->dev_dtr_cmnd[tindex],
X aic7xxx_negotiation_complete);
X }
X }
X
-#endif
-
X #ifdef AIC7XXX_VERBOSE_DEBUGGING


X /*+F*************************************************************************
X * Function:

@@ -9744,8 +10423,9 @@


X {
X unsigned short mask;

X struct aic7xxx_hwscb *hscb;
+ unsigned char tindex = TARGET_INDEX(cmd);
X
- mask = (0x01 << TARGET_INDEX(cmd));
+ mask = (0x01 << tindex);
X hscb = scb->hscb;
X
X /*
@@ -9757,11 +10437,12 @@
X if (p->discenable & mask)
X {
X hscb->control |= DISCENB;
- if (p->tagenable & mask)
+ if ( (p->tagenable & mask) &&
+ (cmd->cmnd[0] != TEST_UNIT_READY) )
X {
X cmd->tag = hscb->tag;
- p->dev_commands_sent[TARGET_INDEX(cmd)]++;
- if (p->dev_commands_sent[TARGET_INDEX(cmd)] < 200)
+ p->dev_commands_sent[tindex]++;
+ if (p->dev_commands_sent[tindex] < 200)
X {
X hscb->control |= MSG_SIMPLE_Q_TAG;
X scb->tag_action = MSG_SIMPLE_Q_TAG;
@@ -9778,74 +10459,38 @@
X hscb->control |= MSG_SIMPLE_Q_TAG;
X scb->tag_action = MSG_SIMPLE_Q_TAG;
X }
- p->dev_commands_sent[TARGET_INDEX(cmd)] = 0;
+ p->dev_commands_sent[tindex] = 0;
X }
X }
X }
- if (p->dev_flags[TARGET_INDEX(cmd)] & DEVICE_SCANNED)
+ if ( cmd == p->dev_dtr_cmnd[tindex] )
X {
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
- if ( (p->needwdtr & mask) && !(p->wdtr_pending & mask) )
+ p->dtr_pending |= mask;


+ scb->tag_action = 0;

+ if (p->dev_flags[tindex] & DEVICE_SCANNED)
X {
- if (cmd == p->dev_wdtr_cmnd[TARGET_INDEX(cmd)])
+ hscb->control &= DISCENB;
+ hscb->control |= MK_MESSAGE;
+ if(p->needppr & mask)
X {
- p->wdtr_pending |= mask;


- scb->flags |= SCB_MSGOUT_WDTR;

- hscb->control &= DISCENB;


- hscb->control |= MK_MESSAGE;

- scb->tag_action = 0;
+ scb->flags |= SCB_MSGOUT_PPR;
X }
- else
+ else if(p->needwdtr & mask)
X {
- aic7xxx_build_negotiation_cmnd(p, cmd, TARGET_INDEX(cmd));


+ scb->flags |= SCB_MSGOUT_WDTR;
X }

- }
- else if ( (p->needsdtr & mask) && !(p->sdtr_pending & mask) &&
- !(p->wdtr_pending & mask) )
- {
- if (cmd == p->dev_sdtr_cmnd[TARGET_INDEX(cmd)])
+ else if(p->needsdtr & mask)
X {
- p->sdtr_pending |= mask;


X scb->flags |= SCB_MSGOUT_SDTR;

- hscb->control &= DISCENB;


- hscb->control |= MK_MESSAGE;

- scb->tag_action = 0;
- }
- else if (cmd != p->dev_wdtr_cmnd[TARGET_INDEX(cmd)])
- {
- aic7xxx_build_negotiation_cmnd(p, cmd, TARGET_INDEX(cmd));
X }
X }
-#else
- if ( (p->needwdtr & mask) && !(p->wdtr_pending & mask) &&
- !(p->sdtr_pending & mask) && (cmd->lun == 0) )
- {
- p->wdtr_pending |= mask;


- scb->flags |= SCB_MSGOUT_WDTR;

- hscb->control &= DISCENB;


- hscb->control |= MK_MESSAGE;

- scb->tag_action = 0;


-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)

- printk(INFO_LEAD "Building WDTR command.\n", p->host_no,
- CTL_OF_CMD(cmd));
-#endif
- }
- else if ( (p->needsdtr & mask) && !(p->wdtr_pending & mask) &&
- !(p->sdtr_pending & mask) && (cmd->lun == 0) )
- {
- p->sdtr_pending |= mask;


- scb->flags |= SCB_MSGOUT_SDTR;

- hscb->control &= DISCENB;


- hscb->control |= MK_MESSAGE;

- scb->tag_action = 0;


-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)

- printk(INFO_LEAD "Building SDTR command.\n", p->host_no,
- CTL_OF_CMD(cmd));
-#endif
- }
-#endif
+ }
+ if ( !(p->dtr_pending & mask) &&
+ ( (p->needppr & mask) ||
+ (p->needwdtr & mask) ||
+ (p->needsdtr & mask) ) )
+ {
+ aic7xxx_build_negotiation_cmnd(p, cmd, tindex);
X }
X hscb->target_channel_lun = ((cmd->target << 4) & 0xF0) |
X ((cmd->channel & 0x01) << 3) | (cmd->lun & 0x07);
@@ -9897,7 +10542,6 @@
X scb->sg_count = cmd->use_sg;
X hscb->SG_segment_count = cmd->use_sg;
X hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(&scb->sg_list[1]));
-
X }
X else
X {
@@ -9922,12 +10566,6 @@
X hscb->data_pointer = 0;
X }
X }
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if((cmd->cmnd[0] == TEST_UNIT_READY) && (aic7xxx_verbose & VERBOSE_PROBE2))
- {
- aic7xxx_print_scb(p, scb);
- }
-#endif
X }
X
X /*+F*************************************************************************
@@ -10262,13 +10900,14 @@
X if(p->dev_flags[i] & DEVICE_PRESENT)
X {


X mask = (0x01 << i);

- printk(INFO_LEAD "dev_flags=0x%x, WDTR:%c/%c/%c, SDTR:%c/%c/%c,"
- " q_depth=%d:%d\n",
+ printk(INFO_LEAD "dev_flags=0x%x, Pending:%c, PPR:%c/%c, WDTR:%c/%c, "
+ "SDTR:%c/%c, q_depth=%d:%d\n",
X p->host_no, 0, i, 0, p->dev_flags[i],
- (p->wdtr_pending & mask) ? 'Y' : 'N',
+ (p->dtr_pending & mask) ? 'Y' : 'N',
+ (p->needppr & mask) ? 'Y' : 'N',
+ (p->needppr_copy & mask) ? 'Y' : 'N',
X (p->needwdtr & mask) ? 'Y' : 'N',
X (p->needwdtr_copy & mask) ? 'Y' : 'N',
- (p->sdtr_pending & mask) ? 'Y' : 'N',
X (p->needsdtr & mask) ? 'Y' : 'N',
X (p->needsdtr_copy & mask) ? 'Y' : 'N',
X p->dev_active_cmds[i],
@@ -10347,13 +10986,13 @@
X * We haven't found the offending SCB yet, and it should be around
X * somewhere, so go look for it in the cards SCBs.
X */
- printk("SCBPTR CONTROL TAG PREV NEXT\n");
+ printk("SCBPTR CONTROL TAG NEXT\n");
X for(i=0; i<p->scb_data->maxhscbs; i++)
X {
X aic_outb(p, i, SCBPTR);
- printk(" %3d %02x %02x %02x %02x\n", i,
+ printk(" %3d %02x %02x %02x\n", i,
X aic_inb(p, SCB_CONTROL), aic_inb(p, SCB_TAG),
- aic_inb(p, SCB_PREV), aic_inb(p, SCB_NEXT));
+ aic_inb(p, SCB_NEXT));
X }
X }
X
@@ -10569,21 +11208,13 @@
X if ((found == 0) && (scb->flags & SCB_WAITINGQ))
X {
X int tindex = TARGET_INDEX(cmd);
-#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS


X unsigned short mask;
X

X mask = (1 << tindex);
X
- if (p->wdtr_pending & mask)
- {
- if (p->dev_wdtr_cmnd[tindex]->next != cmd)
- found = 1;
- else
- found = 0;
- }
- else if (p->sdtr_pending & mask)
+ if (p->dtr_pending & mask)
X {
- if (p->dev_sdtr_cmnd[tindex]->next != cmd)
+ if (p->dev_dtr_cmnd[tindex]->next != cmd)
X found = 1;
X else
X found = 0;
@@ -10606,7 +11237,6 @@
X DRIVER_UNLOCK
X return(SCSI_ABORT_PENDING);
X }
-#endif
X if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
X printk(INFO_LEAD "SCB found on waiting list and "
X "aborted.\n", p->host_no, CTL_OF_SCB(scb));
@@ -10864,6 +11494,8 @@
X if(aic7xxx_verbose & VERBOSE_RESET_RETURN)
X printk(INFO_LEAD "SCB on qoutfifo, returning.\n", p->host_no,
X CTL_OF_SCB(scb));
+ aic7xxx_run_done_queue(p, TRUE);
+ aic7xxx_run_waiting_queues(p);
X unpause_sequencer(p, FALSE);
X DRIVER_UNLOCK
X return(SCSI_RESET_NOT_RUNNING);
@@ -11034,16 +11666,21 @@
X int
X aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[])
X {
- int heads, sectors, cylinders;
+ int heads, sectors, cylinders, ret;
X struct aic7xxx_host *p;
+ struct buffer_head *bh;
X
X p = (struct aic7xxx_host *) disk->device->host->hostdata;
+ bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024);
X
- /*
- * XXX - if I could portably find the card's configuration
- * information, then this could be autodetected instead
- * of left to a boot-time switch.
- */
+ if ( bh )
+ {
+ ret = scsi_partsize(bh, disk->capacity, &geom[2], &geom[0], &geom[1]);
+ brelse(bh);
+ if ( ret != -1 )
+ return(ret);
+ }
+
X heads = 64;
X sectors = 32;
X cylinders = disk->capacity / (heads * sectors);
@@ -11150,6 +11787,12 @@
X 0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9f, 0x9f,
X 0xe0, 0xf1, 0xf4, 0xf4, 0xf6, 0xf6, 0xf8, 0xf8, 0xfa, 0xfc,
X 0xfe, 0xff} },
+ {12, {0x00, 0x05, 0x08, 0x11, 0x18, 0x1f, 0x60, 0x60, 0x62, 0x66, /*7892*/
+ 0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
+ 0xe0, 0xf1, 0xf4, 0xfc} },
+ {12, {0x00, 0x05, 0x08, 0x11, 0x18, 0x1f, 0x60, 0x60, 0x62, 0x66, /*7899*/
+ 0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
+ 0xe0, 0xf1, 0xf4, 0xfc} },
X };
X #ifdef CONFIG_PCI
X static struct register_ranges cards_ns[] = {
@@ -11164,6 +11807,10 @@
X { 5, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3} },
X { 6, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x30, 0x34, 0x3c, 0x47,
X 0xdc, 0xe3} },
+ { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
+ 0xff, 0xff} },
+ { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
+ 0xff, 0xff} },
X { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
X 0xff, 0xff} }
X };
diff -u --recursive --new-file v2.3.5/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- v2.3.5/linux/drivers/scsi/aic7xxx_proc.c Mon Jan 4 12:57:44 1999
+++ linux/drivers/scsi/aic7xxx_proc.c Wed Jun 9 16:59:15 1999
@@ -160,21 +160,17 @@
X size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
X size += sprintf(BLS, "\n");
X size += sprintf(BLS, "Compile Options:\n");
-#ifdef AIC7XXX_RESET_DELAY
- size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY);
+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+ size += sprintf(BLS, " TCQ Enabled By Default : Enabled\n");
+#else
+ size += sprintf(BLS, " TCQ Enabled By Default : Disabled\n");
X #endif
- size += sprintf(BLS, " AIC7XXX_TAGGED_QUEUEING: Adapter Support Enabled\n");
- size += sprintf(BLS, " Check below to see "
- "which\n"
- " devices use tagged "
- "queueing\n");
- size += sprintf(BLS, " AIC7XXX_PAGE_ENABLE : Enabled (This is no longer "
- "an option)\n");
X #ifdef AIC7XXX_PROC_STATS
X size += sprintf(BLS, " AIC7XXX_PROC_STATS : Enabled\n");
X #else
X size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n");
X #endif
+ size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY);
X size += sprintf(BLS, "\n");
X size += sprintf(BLS, "Adapter Configuration:\n");
X size += sprintf(BLS, " SCSI Adapter: %s\n",
@@ -194,8 +190,21 @@
X }
X if (p->features & AHC_WIDE)
X wide = "Wide ";


- if (p->features & AHC_ULTRA2)

- ultra = "Ultra2-LVD/SE ";


+ if (p->features & AHC_ULTRA3)

+ {
+ switch(p->chip & AHC_CHIPID_MASK)
+ {
+ case AHC_AIC7892:
+ case AHC_AIC7899:
+ ultra = "Ultra-160/m LVD/SE ";
+ break;
+ default:
+ ultra = "Ultra-3 LVD/SE ";
+ break;
+ }
+ }


+ else if (p->features & AHC_ULTRA2)

+ ultra = "Ultra-2 LVD/SE ";


X else if (p->features & AHC_ULTRA)

X ultra = "Ultra ";
X size += sprintf(BLS, " %s%sController%s\n",
@@ -250,11 +259,7 @@
X }
X size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable);
X size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag);
-#ifdef AIC7XXX_CMDS_PER_LUN
- size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_LUN);
-#else
- size += sprintf(BLS, "Default Tag Queue Depth: %d\n", 8);
-#endif
+ size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE);
X size += sprintf(BLS, " Tagged Queue By Device array for aic7xxx host "
X "instance %d:\n", p->instance);
X size += sprintf(BLS, " {");
@@ -295,11 +300,12 @@
X if (p->transinfo[target].cur_offset != 0)
X {
X struct aic7xxx_syncrate *sync_rate;
+ unsigned char options = p->transinfo[target].cur_options;
X int period = p->transinfo[target].cur_period;
X int rate = (p->transinfo[target].cur_width ==
X MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
X
- sync_rate = aic7xxx_find_syncrate(p, &period, AHC_SYNCRATE_ULTRA2);
+ sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
X if (sync_rate != NULL)
X {
X size += sprintf(BLS, "%s MByte/sec, offset %d\n",
@@ -313,18 +319,21 @@
X }
X }
X size += sprintf(BLS, " Transinfo settings: ");
- size += sprintf(BLS, "current(%d/%d/%d), ",
+ size += sprintf(BLS, "current(%d/%d/%d/%d), ",
X p->transinfo[target].cur_period,
X p->transinfo[target].cur_offset,
- p->transinfo[target].cur_width);
- size += sprintf(BLS, "goal(%d/%d/%d), ",
+ p->transinfo[target].cur_width,
+ p->transinfo[target].cur_options);
+ size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
X p->transinfo[target].goal_period,
X p->transinfo[target].goal_offset,
- p->transinfo[target].goal_width);
- size += sprintf(BLS, "user(%d/%d/%d)\n",
+ p->transinfo[target].goal_width,
+ p->transinfo[target].goal_options);
+ size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
X p->transinfo[target].user_period,
X p->transinfo[target].user_offset,
- p->transinfo[target].user_width);
+ p->transinfo[target].user_width,
+ p->transinfo[target].user_options);
X #ifdef AIC7XXX_PROC_STATS
X size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n",
X sp->r_total + sp->w_total, sp->r_total, sp->w_total);
diff -u --recursive --new-file v2.3.5/linux/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h
--- v2.3.5/linux/drivers/scsi/aic7xxx_reg.h Thu Oct 8 08:07:34 1998
+++ linux/drivers/scsi/aic7xxx_reg.h Wed Jun 9 16:59:15 1999
@@ -63,6 +63,16 @@
X
X #define STCNT 0x08
X
+#define OPTIONMODE 0x08
+#define AUTORATEEN 0x80
+#define AUTOACKEN 0x40
+#define ATNMGMNTEN 0x20
+#define BUSFREEREV 0x10
+#define EXPPHASEDIS 0x08
+#define SCSIDATL_IMGEN 0x04
+#define AUTO_MSGOUT_DE 0x02
+#define DIS_MSGIN_DUALEDGE 0x01
+
X #define CLRSINT0 0x0b
X #define CLRSELDO 0x40
X #define CLRSELDI 0x20
@@ -102,8 +112,14 @@
X
X #define SSTAT2 0x0d
X #define OVERRUN 0x80
+#define SHVALID 0x40
+#define WIDE_RES 0x20
X #define SFCNT 0x1f
X #define EXP_ACTIVE 0x10
+#define CRCVALERR 0x08
+#define CRCENDERR 0x04
+#define CRCREQERR 0x02
+#define DUAL_EDGE_ERROR 0x01
X
X #define SSTAT3 0x0e
X #define SCSICNT 0xf0
@@ -412,6 +428,7 @@
X #define DPARERR 0x10
X #define SQPARERR 0x08
X #define ILLOPCODE 0x04
+#define DSCTMOUT 0x02
X #define ILLSADDR 0x02
X #define ILLHADDR 0x01
X
@@ -436,11 +453,30 @@
X
X #define QINCNT 0x9c
X
+#define SCSIDATL_IMG 0x9c
+
X #define QOUTFIFO 0x9d
X
+#define CRCCONTROL1 0x9d
+#define CRCONSEEN 0x80
+#define TARGCRCCNTEN 0x40
+#define CRCVALCHKEN 0x40
+#define CRCENDCHKEN 0x20
+#define CRCREQCHKEN 0x10
+#define TARGCRCENDEN 0x08
+
+#define SCSIPHASE 0x9e
+#define SP_STATUS 0x20
+#define SP_COMMAND 0x10
+#define SP_MSG_IN 0x08
+#define SP_MSG_OUT 0x04
+#define SP_DATA_IN 0x02
+#define SP_DATA_OUT 0x01
+
X #define QOUTCNT 0x9e
X
X #define SFUNCT 0x9f
+#define ALT_MODE 0x80
X
X #define SCB_CONTROL 0xa0
X #define MK_MESSAGE 0x80
@@ -525,14 +561,20 @@
X
X #define HNSCB_QOFF 0xf4
X
+#define HESCB_QOFF 0xf5
+
X #define SNSCB_QOFF 0xf6
X
+#define SESCB_QOFF 0xf7
+
X #define SDSCB_QOFF 0xf8
X
X #define QOFF_CTLSTA 0xfa
+#define ESTABLISH_SCB_AVAIL 0x80
X #define SCB_AVAIL 0x40
X #define SNSCB_ROLLOVER 0x20
X #define SDSCB_ROLLOVER 0x10
+#define SESCB_ROLLOVER 0x08
X #define SCB_QSIZE 0x07
X #define SCB_QSIZE_256 0x06
X
diff -u --recursive --new-file v2.3.5/linux/drivers/scsi/aic7xxx_seq.c linux/drivers/scsi/aic7xxx_seq.c
--- v2.3.5/linux/drivers/scsi/aic7xxx_seq.c Thu Oct 8 08:07:34 1998
+++ linux/drivers/scsi/aic7xxx_seq.c Wed Jun 9 16:59:16 1999
@@ -3,38 +3,44 @@
X */
X static unsigned char seqprog[] = {
X 0xff, 0x6a, 0x06, 0x08,
+ 0x7f, 0x02, 0x04, 0x08,
X 0x32, 0x6a, 0x00, 0x00,
X 0x12, 0x6a, 0x00, 0x00,
X 0xff, 0x6a, 0xd6, 0x09,
X 0xff, 0x6a, 0xdc, 0x09,
- 0x00, 0x65, 0x38, 0x59,
+ 0x00, 0x65, 0x42, 0x59,
X 0xf7, 0x01, 0x02, 0x08,
X 0xff, 0x4e, 0xc8, 0x08,
X 0xbf, 0x60, 0xc0, 0x08,
- 0x60, 0x0b, 0x7c, 0x68,
+ 0x60, 0x0b, 0x86, 0x68,
X 0x40, 0x00, 0x0e, 0x68,
X 0x08, 0x1f, 0x3e, 0x10,
- 0x60, 0x0b, 0x7c, 0x68,
+ 0x60, 0x0b, 0x86, 0x68,
X 0x40, 0x00, 0x0e, 0x68,
X 0x08, 0x1f, 0x3e, 0x10,
- 0xff, 0x3e, 0x3e, 0x60,
- 0x40, 0xfa, 0x10, 0x78,
+ 0xff, 0x3e, 0x4a, 0x60,
+ 0x40, 0xfa, 0x12, 0x78,
X 0xff, 0xf6, 0xd4, 0x08,
X 0x01, 0x4e, 0x9c, 0x18,
X 0x40, 0x60, 0xc0, 0x00,
- 0x00, 0x4d, 0x10, 0x70,
+ 0x00, 0x4d, 0x12, 0x70,
X 0x01, 0x4e, 0x9c, 0x18,
X 0xbf, 0x60, 0xc0, 0x08,
- 0x00, 0x6a, 0x72, 0x5c,
+ 0x00, 0x6a, 0x92, 0x5c,
X 0xff, 0x4e, 0xc8, 0x18,
- 0x02, 0x6a, 0x88, 0x5b,
+ 0x02, 0x6a, 0xa8, 0x5b,
X 0xff, 0x52, 0x20, 0x09,
X 0x0d, 0x6a, 0x6a, 0x00,
- 0x00, 0x52, 0xfe, 0x5b,
+ 0x00, 0x52, 0x1e, 0x5c,
+ 0x03, 0xb0, 0x52, 0x31,
+ 0xff, 0xb0, 0x52, 0x09,
+ 0xff, 0xb1, 0x54, 0x09,
+ 0xff, 0xb2, 0x56, 0x09,
+ 0xff, 0xa3, 0x50, 0x09,
X 0xff, 0x3e, 0x74, 0x09,
X 0xff, 0x90, 0x7c, 0x08,
X 0xff, 0x3e, 0x20, 0x09,
- 0x00, 0x65, 0x44, 0x58,
+ 0x00, 0x65, 0x50, 0x58,
X 0x00, 0x65, 0x0e, 0x40,
X 0xf7, 0x1f, 0xca, 0x08,
X 0x08, 0xa1, 0xc8, 0x08,
@@ -47,51 +53,50 @@
X 0x0f, 0x05, 0x0a, 0x08,
X 0x00, 0x05, 0x0a, 0x00,
X 0x5a, 0x6a, 0x00, 0x04,
- 0x12, 0x65, 0xc8, 0x00,
- 0x00, 0x01, 0x02, 0x00,
+ 0x12, 0x65, 0x02, 0x00,
X 0x31, 0x6a, 0xca, 0x00,
- 0x80, 0x37, 0x64, 0x68,
+ 0x80, 0x37, 0x6e, 0x68,
X 0xff, 0x65, 0xca, 0x18,
X 0xff, 0x37, 0xdc, 0x08,
X 0xff, 0x6e, 0xc8, 0x08,
- 0x00, 0x6c, 0x6c, 0x78,
+ 0x00, 0x6c, 0x76, 0x78,
X 0x20, 0x01, 0x02, 0x00,
X 0x4c, 0x37, 0xc8, 0x28,
- 0x08, 0x1f, 0x74, 0x78,
+ 0x08, 0x1f, 0x7e, 0x78,
X 0x08, 0x37, 0x6e, 0x00,
X 0x08, 0x64, 0xc8, 0x00,
X 0x70, 0x64, 0xca, 0x18,
X 0xff, 0x6c, 0x0a, 0x08,
X 0x20, 0x64, 0xca, 0x18,
X 0xff, 0x6c, 0x08, 0x0c,
- 0x40, 0x0b, 0x04, 0x69,
- 0x80, 0x0b, 0xf6, 0x78,
+ 0x40, 0x0b, 0x0e, 0x69,
+ 0x80, 0x0b, 0x00, 0x79,
X 0xa4, 0x6a, 0x06, 0x00,
X 0x40, 0x6a, 0x16, 0x00,
- 0x10, 0x03, 0xf2, 0x78,
+ 0x10, 0x03, 0xfc, 0x78,
X 0xff, 0x50, 0xc8, 0x08,
X 0x88, 0x6a, 0xcc, 0x00,
- 0x49, 0x6a, 0xee, 0x5b,
+ 0x49, 0x6a, 0x0e, 0x5c,
X 0x01, 0x6a, 0x26, 0x01,
X 0xff, 0x6a, 0xca, 0x08,
X 0x08, 0x01, 0x02, 0x00,
- 0x02, 0x0b, 0x92, 0x78,
+ 0x02, 0x0b, 0x9c, 0x78,
X 0xf7, 0x01, 0x02, 0x08,
X 0xff, 0x06, 0xcc, 0x08,
X 0xff, 0x66, 0x32, 0x09,
X 0x01, 0x65, 0xca, 0x18,
- 0x80, 0x66, 0xa0, 0x78,
+ 0x80, 0x66, 0xaa, 0x78,
X 0xff, 0x66, 0xa2, 0x08,
- 0x10, 0x03, 0x90, 0x68,
+ 0x10, 0x03, 0x9a, 0x68,
X 0xfc, 0x65, 0xc8, 0x18,
- 0x00, 0x65, 0xa8, 0x48,
+ 0x00, 0x65, 0xb2, 0x48,
X 0xff, 0x6a, 0x32, 0x01,
X 0x01, 0x64, 0x18, 0x19,
X 0xff, 0x6a, 0x1a, 0x09,
X 0xff, 0x6a, 0x1c, 0x09,
X 0x84, 0x6a, 0x06, 0x00,
X 0x08, 0x01, 0x02, 0x00,
- 0x02, 0x0b, 0xb2, 0x78,
+ 0x02, 0x0b, 0xbc, 0x78,
X 0xff, 0x06, 0xc8, 0x08,
X 0xff, 0x64, 0x32, 0x09,
X 0xff, 0x6a, 0xca, 0x08,
@@ -105,33 +110,33 @@
X 0x0b, 0x65, 0xca, 0x18,
X 0xff, 0x65, 0xc8, 0x08,
X 0x00, 0x8c, 0x18, 0x19,
- 0x02, 0x0b, 0xce, 0x78,
- 0x01, 0x65, 0xd4, 0x60,
+ 0x02, 0x0b, 0xd8, 0x78,
+ 0x01, 0x65, 0xde, 0x60,
X 0xf7, 0x01, 0x02, 0x08,
X 0xff, 0x06, 0x32, 0x09,
X 0xff, 0x65, 0xca, 0x18,
- 0xff, 0x65, 0xce, 0x68,
+ 0xff, 0x65, 0xd8, 0x68,
X 0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0x64, 0x5c,
- 0x40, 0x51, 0xe6, 0x78,
+ 0x00, 0x65, 0x84, 0x5c,
+ 0x40, 0x51, 0xf0, 0x78,
X 0xe4, 0x6a, 0x06, 0x00,
X 0x08, 0x01, 0x02, 0x00,
- 0x04, 0x6a, 0x18, 0x5b,
+ 0x04, 0x6a, 0x40, 0x5b,
X 0x01, 0x50, 0xa0, 0x18,
- 0x00, 0x50, 0xec, 0xe0,
+ 0x00, 0x50, 0xf6, 0xe0,
X 0xff, 0x6a, 0xa0, 0x08,
X 0xff, 0x6a, 0x3a, 0x01,
X 0x02, 0x6a, 0x22, 0x01,
- 0x40, 0x51, 0xf2, 0x68,
+ 0x40, 0x51, 0xfc, 0x68,
X 0xff, 0x6a, 0x06, 0x08,
X 0x00, 0x65, 0x0e, 0x40,
X 0x20, 0x6a, 0x16, 0x00,
X 0xf0, 0x19, 0x6e, 0x08,
X 0x08, 0x6a, 0x18, 0x00,
X 0x08, 0x11, 0x22, 0x00,
- 0x08, 0x6a, 0x5a, 0x58,
+ 0x08, 0x6a, 0x66, 0x58,
X 0x08, 0x6a, 0x68, 0x00,
- 0x00, 0x65, 0x18, 0x41,
+ 0x00, 0x65, 0x22, 0x41,
X 0x12, 0x6a, 0x00, 0x00,
X 0x40, 0x6a, 0x16, 0x00,
X 0xff, 0x3e, 0x20, 0x09,
@@ -139,362 +144,373 @@
X 0xff, 0xa1, 0x6e, 0x08,
X 0x08, 0x6a, 0x18, 0x00,
X 0x08, 0x11, 0x22, 0x00,
- 0x08, 0x6a, 0x5a, 0x58,
+ 0x08, 0x6a, 0x66, 0x58,
X 0x80, 0x6a, 0x68, 0x00,
X 0x80, 0x36, 0x6c, 0x00,
- 0x00, 0x65, 0xd2, 0x5b,
+ 0x00, 0x65, 0xf2, 0x5b,
X 0xff, 0x3d, 0xc8, 0x08,
- 0xbf, 0x64, 0x48, 0x79,
- 0x80, 0x64, 0xf0, 0x71,
- 0xa0, 0x64, 0x0e, 0x72,
- 0xc0, 0x64, 0x08, 0x72,
- 0xe0, 0x64, 0x52, 0x72,
+ 0xbf, 0x64, 0x58, 0x79,
+ 0x80, 0x64, 0x0e, 0x72,
+ 0xa0, 0x64, 0x3a, 0x72,
+ 0xc0, 0x64, 0x32, 0x72,
+ 0xe0, 0x64, 0x7a, 0x72,
X 0x01, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x18, 0x41,
+ 0x00, 0x65, 0x22, 0x41,
X 0xf7, 0x11, 0x22, 0x08,
- 0x00, 0x65, 0x38, 0x59,
+ 0x00, 0x65, 0x42, 0x59,
X 0xff, 0x06, 0xd4, 0x08,
X 0xf7, 0x01, 0x02, 0x08,
- 0x09, 0x0c, 0x32, 0x79,
+ 0x09, 0x0c, 0x3c, 0x79,
X 0x08, 0x0c, 0x0e, 0x68,
X 0x01, 0x6a, 0x22, 0x01,
X 0xff, 0x6a, 0x26, 0x09,
+ 0x02, 0x6a, 0x08, 0x30,
X 0xff, 0x6a, 0x08, 0x08,
X 0xdf, 0x01, 0x02, 0x08,
X 0x01, 0x6a, 0x7a, 0x00,
- 0x03, 0x36, 0x6c, 0x0c,
+ 0xff, 0x6a, 0x6c, 0x0c,
+ 0x03, 0xa9, 0x18, 0x31,
+ 0x03, 0xa9, 0x10, 0x30,
X 0x08, 0x6a, 0xcc, 0x00,
- 0xa9, 0x6a, 0xe8, 0x5b,
- 0x00, 0x65, 0x66, 0x41,
+ 0xa9, 0x6a, 0x08, 0x5c,
+ 0x00, 0x65, 0x78, 0x41,
X 0xa8, 0x6a, 0x6a, 0x00,
X 0x79, 0x6a, 0x6a, 0x00,
- 0x40, 0x3d, 0x50, 0x69,
+ 0x40, 0x3d, 0x60, 0x69,
X 0x04, 0x35, 0x6a, 0x00,
- 0x00, 0x65, 0x3a, 0x5b,
+ 0x00, 0x65, 0x62, 0x5b,
X 0x80, 0x6a, 0xd4, 0x01,
- 0x10, 0x36, 0x42, 0x69,
+ 0x10, 0x36, 0x4e, 0x69,
X 0x10, 0x36, 0x6c, 0x00,
X 0x07, 0xac, 0x10, 0x31,
+ 0x03, 0x8c, 0x10, 0x30,
+ 0x05, 0xa3, 0x70, 0x30,
X 0x88, 0x6a, 0xcc, 0x00,
- 0xac, 0x6a, 0xe0, 0x5b,
- 0x00, 0x65, 0xda, 0x5b,
- 0xff, 0xa3, 0x70, 0x08,
- 0x39, 0x6a, 0xcc, 0x00,
- 0xa4, 0x6a, 0xe6, 0x5b,
- 0xff, 0x38, 0x74, 0x69,
+ 0xac, 0x6a, 0x00, 0x5c,
+ 0x00, 0x65, 0xfa, 0x5b,
+ 0x38, 0x6a, 0xcc, 0x00,
+ 0xa3, 0x6a, 0x04, 0x5c,
+ 0xff, 0x38, 0x88, 0x69,
X 0x80, 0x02, 0x04, 0x00,
X 0xe7, 0x35, 0x6a, 0x08,
X 0x03, 0x69, 0x18, 0x31,
+ 0x03, 0x69, 0x10, 0x30,
X 0xff, 0x6a, 0x10, 0x00,
X 0xff, 0x6a, 0x12, 0x00,
X 0xff, 0x6a, 0x14, 0x00,
- 0x01, 0x38, 0x7a, 0x61,
- 0x02, 0xfc, 0xf8, 0x01,
+ 0x01, 0x38, 0x8c, 0x61,
X 0xbf, 0x35, 0x6a, 0x08,
X 0xff, 0x69, 0xca, 0x08,
X 0xff, 0x35, 0x26, 0x09,
- 0x04, 0x0b, 0x7e, 0x69,
- 0x04, 0x0b, 0x8a, 0x69,
- 0x10, 0x0c, 0x80, 0x79,
- 0x04, 0x0b, 0x88, 0x69,
+ 0x04, 0x0b, 0x90, 0x69,
+ 0x04, 0x0b, 0x9c, 0x69,
+ 0x10, 0x0c, 0x92, 0x79,
+ 0x04, 0x0b, 0x9a, 0x69,
X 0xff, 0x6a, 0xca, 0x08,
- 0x00, 0x35, 0x22, 0x5b,
- 0x80, 0x02, 0xd6, 0x69,
- 0xff, 0x65, 0xc8, 0x79,
+ 0x00, 0x35, 0x4a, 0x5b,
+ 0x80, 0x02, 0xf0, 0x69,
+ 0xff, 0x65, 0xe0, 0x79,
X 0xff, 0x38, 0x70, 0x18,
- 0xff, 0x38, 0xc8, 0x79,
- 0x80, 0xea, 0xaa, 0x61,
+ 0xff, 0x38, 0xe0, 0x79,
+ 0x80, 0xea, 0xbc, 0x61,
X 0xef, 0x38, 0xc8, 0x18,
X 0x80, 0x6a, 0xc8, 0x00,
- 0x00, 0x65, 0x9c, 0x49,
+ 0x00, 0x65, 0xae, 0x49,
X 0x33, 0x38, 0xc8, 0x28,
X 0xff, 0x64, 0xd0, 0x09,
X 0x04, 0x39, 0xc0, 0x31,
X 0x09, 0x6a, 0xd6, 0x01,
- 0x80, 0xeb, 0xa2, 0x79,
+ 0x80, 0xeb, 0xb4, 0x79,
X 0xf7, 0xeb, 0xd6, 0x09,
- 0x08, 0xeb, 0xa6, 0x69,
+ 0x08, 0xeb, 0xb8, 0x69,
X 0x01, 0x6a, 0xd6, 0x01,
X 0x08, 0xe9, 0x10, 0x31,
+ 0x03, 0x8c, 0x10, 0x30,
X 0x88, 0x6a, 0xcc, 0x00,
- 0x39, 0x6a, 0xe6, 0x5b,
+ 0x39, 0x6a, 0x06, 0x5c,
X 0x08, 0x6a, 0x18, 0x01,
X 0xff, 0x6a, 0x1a, 0x09,
X 0xff, 0x6a, 0x1c, 0x09,
X 0x0d, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0x64, 0x5c,
- 0x88, 0x6a, 0x54, 0x5c,
- 0x00, 0x65, 0xda, 0x5b,
+ 0x00, 0x65, 0x84, 0x5c,
+ 0x88, 0x6a, 0x74, 0x5c,
+ 0x00, 0x65, 0xfa, 0x5b,
X 0xff, 0x6a, 0xc8, 0x08,
X 0x08, 0x39, 0x72, 0x18,
X 0x00, 0x3a, 0x74, 0x20,
- 0x10, 0x0c, 0x66, 0x79,
- 0x80, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xe0, 0x59,
+ 0x01, 0x0c, 0xd8, 0x79,
+ 0x10, 0x0c, 0x78, 0x79,
+ 0xff, 0x35, 0x26, 0x09,
+ 0x04, 0x0b, 0xde, 0x69,
+ 0x00, 0x65, 0xf8, 0x59,
+ 0x03, 0x08, 0x52, 0x31,
+ 0xff, 0x38, 0x50, 0x09,
X 0xff, 0x08, 0x52, 0x09,
X 0xff, 0x09, 0x54, 0x09,
X 0xff, 0x0a, 0x56, 0x09,
X 0xff, 0x38, 0x50, 0x09,
- 0x12, 0x01, 0x02, 0x00,
- 0x00, 0x65, 0x18, 0x41,
- 0x00, 0x65, 0xe0, 0x59,
- 0x12, 0x01, 0x02, 0x00,
+ 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0xf8, 0x59,
X 0x7f, 0x02, 0x04, 0x08,
X 0xe1, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x18, 0x41,
- 0x04, 0x93, 0xea, 0x69,
+ 0x00, 0x65, 0x22, 0x41,
+ 0x04, 0x93, 0x02, 0x6a,
X 0xdf, 0x93, 0x26, 0x09,
- 0x20, 0x93, 0xe4, 0x69,
+ 0x20, 0x93, 0xfc, 0x69,
X 0x02, 0x93, 0x26, 0x01,
- 0x01, 0x94, 0xe6, 0x79,
+ 0x01, 0x94, 0xfe, 0x79,
X 0xd7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0xec, 0x69,
+ 0x08, 0x93, 0x04, 0x6a,
+ 0x03, 0x08, 0x52, 0x31,
+ 0xff, 0x38, 0x50, 0x09,
+ 0x12, 0x01, 0x02, 0x00,
X 0xff, 0x6a, 0xd4, 0x0c,
- 0x00, 0x65, 0x3a, 0x5b,
- 0x02, 0xfc, 0xf8, 0x01,
+ 0x00, 0x65, 0x62, 0x5b,
X 0x05, 0xb4, 0x10, 0x31,
X 0x02, 0x6a, 0x1a, 0x31,
+ 0x03, 0x8c, 0x10, 0x30,
X 0x88, 0x6a, 0xcc, 0x00,
- 0xb4, 0x6a, 0xe4, 0x5b,
+ 0xb4, 0x6a, 0x04, 0x5c,
X 0xff, 0x6a, 0x1a, 0x09,
X 0xff, 0x6a, 0x1c, 0x09,
- 0x00, 0x65, 0xda, 0x5b,
- 0x3d, 0x6a, 0x22, 0x5b,
- 0xac, 0x6a, 0x22, 0x5b,
- 0x00, 0x65, 0x18, 0x41,
- 0x00, 0x65, 0x3a, 0x5b,
+ 0x00, 0x65, 0xfa, 0x5b,
+ 0x3d, 0x6a, 0x4a, 0x5b,
+ 0xac, 0x6a, 0x26, 0x01,
+ 0x04, 0x0b, 0x24, 0x6a,
+ 0x01, 0x0b, 0x2a, 0x6a,
+ 0x10, 0x0c, 0x26, 0x7a,
+ 0xd7, 0x93, 0x26, 0x09,
+ 0x08, 0x93, 0x2c, 0x6a,
+ 0x12, 0x01, 0x02, 0x00,
+ 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0x62, 0x5b,
X 0xff, 0x06, 0x44, 0x09,
- 0x00, 0x65, 0x18, 0x41,
+ 0x00, 0x65, 0x22, 0x41,
+ 0x10, 0x3d, 0x06, 0x00,
X 0xff, 0x34, 0xca, 0x08,
- 0x80, 0x65, 0x32, 0x62,
+ 0x80, 0x65, 0x5e, 0x62,
X 0x0f, 0xa1, 0xca, 0x08,
X 0x07, 0xa1, 0xca, 0x08,
X 0x40, 0xa0, 0xc8, 0x08,
X 0x00, 0x65, 0xca, 0x00,
X 0x80, 0x65, 0xca, 0x00,
- 0x80, 0xa0, 0x22, 0x7a,
+ 0x80, 0xa0, 0x4e, 0x7a,
X 0xff, 0x65, 0x0c, 0x08,
- 0x00, 0x65, 0x34, 0x42,
- 0x20, 0xa0, 0x3a, 0x7a,
+ 0x00, 0x65, 0x60, 0x42,
+ 0x20, 0xa0, 0x66, 0x7a,
X 0xff, 0x65, 0x0c, 0x08,
- 0x00, 0x65, 0xd2, 0x5b,
- 0xa0, 0x3d, 0x46, 0x62,
+ 0x00, 0x65, 0xf2, 0x5b,
+ 0xa0, 0x3d, 0x6e, 0x62,
X 0x23, 0xa0, 0x0c, 0x08,
- 0x00, 0x65, 0xd2, 0x5b,
- 0xa0, 0x3d, 0x46, 0x62,
- 0x00, 0xb9, 0x3a, 0x42,
- 0xff, 0x65, 0x3a, 0x62,
+ 0x00, 0x65, 0xf2, 0x5b,
+ 0xa0, 0x3d, 0x6e, 0x62,
+ 0x00, 0xb9, 0x66, 0x42,
+ 0xff, 0x65, 0x66, 0x62,
X 0xa1, 0x6a, 0x22, 0x01,
X 0xff, 0x6a, 0xd4, 0x08,
- 0x10, 0x51, 0x46, 0x72,
+ 0x10, 0x51, 0x6e, 0x72,
X 0x40, 0x6a, 0x18, 0x00,
X 0xff, 0x65, 0x0c, 0x08,
- 0x00, 0x65, 0xd2, 0x5b,
- 0xa0, 0x3d, 0x46, 0x62,
- 0x10, 0x3d, 0x06, 0x00,
- 0x00, 0x65, 0x0e, 0x42,
+ 0x00, 0x65, 0xf2, 0x5b,
+ 0xa0, 0x3d, 0x38, 0x72,
X 0x40, 0x6a, 0x18, 0x00,
X 0xff, 0x34, 0xa6, 0x08,
- 0x80, 0x34, 0x4e, 0x62,
+ 0x80, 0x34, 0x76, 0x62,
X 0x7f, 0xa0, 0x40, 0x09,
X 0x08, 0x6a, 0x68, 0x00,
- 0x00, 0x65, 0x18, 0x41,
- 0x64, 0x6a, 0x12, 0x5b,
- 0x80, 0x64, 0xbe, 0x6a,
- 0x04, 0x64, 0xa4, 0x72,
- 0x02, 0x64, 0xaa, 0x72,
- 0x00, 0x6a, 0x6c, 0x72,
- 0x03, 0x64, 0xba, 0x72,
- 0x01, 0x64, 0xa0, 0x72,
- 0x07, 0x64, 0x00, 0x73,
- 0x08, 0x64, 0x68, 0x72,
+ 0x00, 0x65, 0x22, 0x41,
+ 0x64, 0x6a, 0x3a, 0x5b,
+ 0x80, 0x64, 0xea, 0x6a,
+ 0x04, 0x64, 0xcc, 0x72,
+ 0x02, 0x64, 0xd2, 0x72,
+ 0x00, 0x6a, 0x94, 0x72,
+ 0x03, 0x64, 0xe6, 0x72,
+ 0x01, 0x64, 0xc8, 0x72,
+ 0x07, 0x64, 0x28, 0x73,
+ 0x08, 0x64, 0x90, 0x72,
X 0x11, 0x6a, 0x22, 0x01,
- 0x07, 0x6a, 0x04, 0x5b,
+ 0x07, 0x6a, 0x2c, 0x5b,
X 0xff, 0x06, 0xd4, 0x08,
- 0x00, 0x65, 0x18, 0x41,
- 0xff, 0xa8, 0x70, 0x6a,
- 0xff, 0xa2, 0x88, 0x7a,
+ 0x00, 0x65, 0x22, 0x41,
+ 0xff, 0xa8, 0x98, 0x6a,
+ 0xff, 0xa2, 0xb0, 0x7a,
X 0x01, 0x6a, 0x6a, 0x00,
- 0x00, 0xb9, 0xfe, 0x5b,
- 0xff, 0xa2, 0x88, 0x7a,
+ 0x00, 0xb9, 0x1e, 0x5c,
+ 0xff, 0xa2, 0xb0, 0x7a,
X 0x71, 0x6a, 0x22, 0x01,
X 0xff, 0x6a, 0xd4, 0x08,
- 0x40, 0x51, 0x88, 0x62,
+ 0x40, 0x51, 0xb0, 0x62,
X 0x0d, 0x6a, 0x6a, 0x00,
- 0x00, 0xb9, 0xfe, 0x5b,
+ 0x00, 0xb9, 0x1e, 0x5c,
X 0xff, 0x3e, 0x74, 0x09,
X 0xff, 0x90, 0x7c, 0x08,
- 0x00, 0x65, 0x44, 0x58,
- 0x00, 0x65, 0x2a, 0x41,
- 0x20, 0xa0, 0x90, 0x6a,
+ 0x00, 0x65, 0x50, 0x58,
+ 0x00, 0x65, 0x34, 0x41,
+ 0x20, 0xa0, 0xb8, 0x6a,
X 0xff, 0x37, 0xc8, 0x08,
- 0x00, 0x6a, 0xa8, 0x5b,
- 0xff, 0x6a, 0xbe, 0x5b,
+ 0x00, 0x6a, 0xc8, 0x5b,
+ 0xff, 0x6a, 0xde, 0x5b,
X 0xff, 0xf8, 0xc8, 0x08,
X 0xff, 0x4f, 0xc8, 0x08,
- 0x01, 0x6a, 0xa8, 0x5b,
- 0x00, 0xb9, 0xbe, 0x5b,
+ 0x01, 0x6a, 0xc8, 0x5b,
+ 0x00, 0xb9, 0xde, 0x5b,
X 0x01, 0x4f, 0x9e, 0x18,
X 0x02, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x6c, 0x5c,
- 0x00, 0x65, 0x2a, 0x41,
+ 0x00, 0x65, 0x8c, 0x5c,
+ 0x00, 0x65, 0x34, 0x41,
X 0x41, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x18, 0x41,
+ 0x00, 0x65, 0x22, 0x41,
X 0x04, 0xa0, 0x40, 0x01,
- 0x00, 0x65, 0x84, 0x5c,
- 0x00, 0x65, 0x2a, 0x41,
- 0x10, 0x36, 0x68, 0x7a,
- 0xff, 0x38, 0x46, 0x09,
- 0xa4, 0x6a, 0xcc, 0x00,
- 0x39, 0x6a, 0xe6, 0x5b,
+ 0x00, 0x65, 0xa4, 0x5c,
+ 0x00, 0x65, 0x34, 0x41,
+ 0x10, 0x36, 0x90, 0x7a,
+ 0x05, 0x38, 0x46, 0x31,
+ 0x04, 0x14, 0x58, 0x31,
+ 0x03, 0xa9, 0x60, 0x31,
+ 0xa3, 0x6a, 0xcc, 0x00,
+ 0x38, 0x6a, 0x04, 0x5c,
X 0xac, 0x6a, 0xcc, 0x00,
- 0x14, 0x6a, 0xe6, 0x5b,
- 0xa9, 0x6a, 0xe8, 0x5b,


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

echo 'End of part 14'
echo 'File patch-2.3.6 is continued in part 15'
echo 15 > _shar_seq_.tmp

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part16

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


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

if test "$Scheck" != 16; then


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

+ if(schp->use_sg > 0) {
+ int k, mem_src;
+ struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+
+ for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) {
X mem_src = (int)(long)sclp->alt_address;
X SCSI_LOG_TIMEOUT(5,
- printk("sg_sc_undo_rem: k=%d, a=0x%p, len=%d, ms=%d\n",
+ printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n",
X k, sclp->address, sclp->length, mem_src));
- sg_free(srp, sclp->address, sclp->length, mem_src);
+ sg_free(sclp->address, sclp->length, mem_src);
+ sclp->address = NULL;
+ sclp->length = 0;
+ }
+ sg_free(schp->buffer, schp->sglist_len, schp->mem_src);
+ }
+ else if (schp->buffer)
+ sg_free(schp->buffer, schp->b_malloc_len, schp->mem_src);
+ schp->buffer = NULL;
+ schp->bufflen = 0;
+ schp->use_sg = 0;
+ schp->sglist_len = 0;
+}
+
+static void sg_read_xfer(Sg_scatter_hold * schp, char * outp,
+ int num_read_xfer)
+{
+ SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_read_xfer=%d\n",
+ num_read_xfer));
+ if ((! outp) || (num_read_xfer <= 0))
+ return;
+ if(schp->use_sg > 0) {
+ int k, num;
+ struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+
+ for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) {
+ num = (int)sclp->length;
+ if (num > num_read_xfer) {
+ __copy_to_user(outp, sclp->address, num_read_xfer);
+ break;
+ }
+ else {
+ __copy_to_user(outp, sclp->address, num);
+ num_read_xfer -= num;
+ if (num_read_xfer <= 0)
+ break;
+ outp += num;
+ }
X }
- sg_free(srp, srp->data.buffer, srp->data.sglist_len,
- srp->data.mem_src);
+ }
+ else
+ __copy_to_user(outp, schp->buffer, num_read_xfer);
+}
+
+static void sg_build_reserve(Sg_fd * sfp, int req_size)
+{
+ Sg_scatter_hold * schp = &sfp->reserve;
+
+ SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size));
+ do {
+ if (req_size < PAGE_SIZE)
+ req_size = PAGE_SIZE;
+ if (0 == sg_build_scat(schp, req_size, sfp))
+ return;
+ else
+ sg_remove_scat(schp);
+ req_size >>= 1; /* divide by 2 */
+ } while (req_size > (PAGE_SIZE / 2));
+}
+
+static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
+{
+ Sg_scatter_hold * req_schp = &srp->data;
+ Sg_scatter_hold * rsv_schp = &sfp->reserve;
+
+ SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
+ if (rsv_schp->use_sg > 0) {
+ int k, num;
+ int rem = size;
+ struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
+
+ for (k = 0; k < rsv_schp->use_sg; ++k, ++sclp) {
+ num = (int)sclp->length;
+ if (rem <= num) {
+ sfp->save_scat_len = num;
+ sclp->length = (unsigned)rem;
+ break;
+ }
+ else
+ rem -= num;
+ }
+ if (k < rsv_schp->use_sg) {
+ req_schp->use_sg = k + 1; /* adjust scatter list length */
+ req_schp->bufflen = size;
+ req_schp->sglist_len = rsv_schp->sglist_len;
+ req_schp->buffer = rsv_schp->buffer;
+ req_schp->mem_src = rsv_schp->mem_src;
+ req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+ }
+ else
+ SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
X }
X else {
- if (num_read_xfer > 0)
- __copy_to_user(outp, srp->data.buffer, num_read_xfer);
- sg_free(srp, srp->data.buffer, srp->data.b_malloc_len,
- srp->data.mem_src);
- }
- if (0 == sg_remove_request(srp->parentfp, srp)) {
- SCSI_LOG_TIMEOUT(1, printk("sg_sc_undo_rem: srp=0x%p not found\n",
- srp));
+ req_schp->use_sg = 0;
+ req_schp->bufflen = size;
+ req_schp->buffer = rsv_schp->buffer;
+ req_schp->mem_src = rsv_schp->mem_src;
+ req_schp->use_sg = rsv_schp->use_sg;
+ req_schp->b_malloc_len = rsv_schp->b_malloc_len;
X }
- return 0;
+ srp->res_used = 1;
+}
+
+static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
+{
+ Sg_scatter_hold * req_schp = &srp->data;
+ Sg_scatter_hold * rsv_schp = &sfp->reserve;
+
+ SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->use_sg=%d\n",
+ (int)req_schp->use_sg));
+ if (rsv_schp->use_sg > 0) {
+ struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
+
+ if (sfp->save_scat_len > 0)
+ (sclp + (req_schp->use_sg - 1))->length =
+ (unsigned)sfp->save_scat_len;
+ else
+ SCSI_LOG_TIMEOUT(1, printk(
+ "sg_unlink_reserve: BAD save_scat_len\n"));
+ }
+ req_schp->use_sg = 0;
+ req_schp->bufflen = 0;
+ req_schp->buffer = NULL;
+ req_schp->sglist_len = 0;
+ sfp->save_scat_len = 0;
+ srp->res_used = 0;
X }
X
X static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id)
@@ -1292,7 +1449,7 @@
X if (resp) {
X resp->parentfp = sfp;
X resp->nextrp = NULL;
- resp->fb_used = 0;
+ resp->res_used = 0;
X memset(&resp->data, 0, sizeof(Sg_scatter_hold));
X memset(&resp->header, 0, sizeof(struct sg_header));
X resp->my_cmdp = NULL;
@@ -1347,13 +1504,6 @@
X sdp->device->host->unchecked_isa_dma : 1;
X sfp->cmd_q = SG_DEF_COMMAND_Q;
X sfp->underrun_flag = SG_DEF_UNDERRUN_FLAG;
- if (get_reserved)
- sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, sfp->low_dma,
- SG_HEAP_PAGE, &sfp->fb_size);
- else
- sfp->fst_buf = NULL;
- if (! sfp->fst_buf)
- sfp->fb_size = 0;
X sfp->parentdp = sdp;
X if (! sdp->headfp)
X sdp->headfp = sfp;
@@ -1363,11 +1513,14 @@
X pfp = pfp->nextfp;
X pfp->nextfp = sfp;
X }
- sg_big_buff = sfp->fb_size; /* show sysctl most recent "fb" size */
X SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n",
X sfp, (int)sfp->my_mem_src));
- SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: fb_sz=%d, fst_buf=0x%p\n",
- sfp->fb_size, sfp->fst_buf));
+ if (get_reserved) {
+ sg_build_reserve(sfp, SG_DEF_RESERVED_SIZE);
+ sg_big_buff = sfp->reserve.bufflen; /* sysctl shows most recent size */
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, use_sg=%d\n",
+ sfp->reserve.bufflen, sfp->reserve.use_sg));
+ }
X return sfp;
X }
X
@@ -1388,7 +1541,7 @@
X while (srp) {
X tsrp = srp->nextrp;
X if (! srp->my_cmdp)
- sg_sc_undo_rem(srp, NULL, 0);
+ sg_finish_rem_req(srp, NULL, 0);
X else
X ++dirty;
X srp = tsrp;
@@ -1409,12 +1562,12 @@
X prev_fp = fp;
X }
X }
-SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: fb_sz=%d, fst_buf=0x%p\n",
- sfp->fb_size, sfp->fst_buf));
- sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
+ if (sfp->reserve.bufflen > 0) {
+SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: bufflen=%d, use_sg=%d\n",
+ (int)sfp->reserve.bufflen, (int)sfp->reserve.use_sg));
+ sg_remove_scat(&sfp->reserve);
+ }
X sfp->parentdp = NULL;
- sfp->fst_buf = NULL;
- sfp->fb_size = 0;
X SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%p\n", sfp));
X sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->my_mem_src);
X res = 1;
@@ -1427,12 +1580,12 @@
X return res;
X }
X
-static int sg_fb_in_use(const Sg_fd * sfp)
+static int sg_res_in_use(const Sg_fd * sfp)
X {
X const Sg_request * srp = sfp->headrp;
X
X while (srp) {
- if (srp->fb_used)
+ if (srp->res_used)
X return 1;
X srp = srp->nextrp;
X }
@@ -1511,7 +1664,7 @@
X return resp;
X }
X
-static char * sg_malloc(Sg_request * srp, int size, int * retSzp,
+static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp,
X int * mem_srcp)
X {
X char * resp = NULL;
@@ -1520,26 +1673,16 @@
X if (size <= 0)
X ;
X else {
- Sg_fd * sfp = srp->parentfp;
X int low_dma = sfp->low_dma;
X int l_ms = -1; /* invalid value */
X
X switch (*mem_srcp)
X {
X case SG_HEAP_PAGE:
- case SG_HEAP_FB:
X l_ms = (size < PAGE_SIZE) ? SG_HEAP_POOL : SG_HEAP_PAGE;
X resp = sg_low_malloc(size, low_dma, l_ms, 0);
X if (resp)
X break;
- if ((size <= sfp->fb_size) && (0 == sg_fb_in_use(sfp))) {
- SCSI_LOG_TIMEOUT(6,
- printk("sg_malloc: scsi_malloc failed, get fst_buf\n"));
- resp = sfp->fst_buf;
- srp->fb_used = 1;
- l_ms = SG_HEAP_FB;
- break;
- }
X resp = sg_low_malloc(size, low_dma, l_ms, &size);
X if (! resp) {
X l_ms = (SG_HEAP_POOL == l_ms) ? SG_HEAP_PAGE : SG_HEAP_POOL;
@@ -1595,18 +1738,12 @@
X mem_src, buff, size);
X }
X
-static void sg_free(Sg_request * srp, char * buff, int size, int mem_src)
+static void sg_free(char * buff, int size, int mem_src)
X {
- Sg_fd * sfp = srp->parentfp;
-
X SCSI_LOG_TIMEOUT(6,
X printk("sg_free: buff=0x%p, size=%d\n", buff, size));
- if ((! sfp) || (! buff) || (size <= 0))
+ if ((! buff) || (size <= 0))
X ;
- else if (sfp->fst_buf == buff) {
- srp->fb_used = 0;
- SCSI_LOG_TIMEOUT(6, printk("sg_free: left cause fst_buf\n"));
- }
X else
X sg_low_free(buff, size, mem_src);
X }
diff -u --recursive --new-file v2.3.5/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.3.5/linux/drivers/sound/dmasound.c Fri May 14 18:55:22 1999
+++ linux/drivers/sound/dmasound.c Mon Jun 7 12:12:22 1999
@@ -784,6 +784,7 @@
X
X struct sound_mixer {
X int busy;
+ int modify_counter;
X };
X
X static struct sound_mixer mixer;
@@ -3811,10 +3812,23 @@
X u_long arg)
X {
X int data;
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+ mixer.modify_counter++;
+ if (cmd == OSS_GETVERSION)
+ return IOCTL_OUT(arg, SOUND_VERSION);
X switch (sound.mach.type) {
X #ifdef CONFIG_ATARI
X case DMASND_FALCON:
X switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "FALCON", sizeof(info.id));
+ strncpy(info.name, "FALCON", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ return 0;
+ }
X case SOUND_MIXER_READ_DEVMASK:
X return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
X case SOUND_MIXER_READ_RECMASK:
@@ -3866,6 +3880,15 @@
X
X case DMASND_TT:
X switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "TT", sizeof(info.id));
+ strncpy(info.name, "TT", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ return 0;
+ }
X case SOUND_MIXER_READ_DEVMASK:
X return IOCTL_OUT(arg,
X SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
@@ -3927,6 +3950,15 @@
X #ifdef CONFIG_AMIGA
X case DMASND_AMIGA:
X switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "AMIGA", sizeof(info.id));
+ strncpy(info.name, "AMIGA", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ return 0;
+ }
X case SOUND_MIXER_READ_DEVMASK:
X return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
X case SOUND_MIXER_READ_RECMASK:
@@ -3953,6 +3985,16 @@
X case DMASND_AWACS:
X if (awacs_revision<AWACS_BURGUNDY) { /* Different IOCTLS for burgundy*/
X switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "AWACS", sizeof(info.id));
+ strncpy(info.name, "AWACS", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info,
+ sizeof(info), -EFAULT);
+ return 0;
+ }
X case SOUND_MIXER_READ_DEVMASK:
X data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
X | SOUND_MASK_LINE | SOUND_MASK_MIC
@@ -4066,6 +4108,16 @@
X } else {
X /* We are, we are, we are... Burgundy or better */
X switch(cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "AWACS", sizeof(info.id));
+ strncpy(info.name, "AWACS", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info,
+ sizeof(info), -EFAULT);
+ return 0;
+ }
X case SOUND_MIXER_READ_DEVMASK:
X data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
X SOUND_MASK_LINE | SOUND_MASK_MIC |
diff -u --recursive --new-file v2.3.5/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.3.5/linux/drivers/sound/sound_core.c Mon May 31 22:28:06 1999
+++ linux/drivers/sound/sound_core.c Mon Jun 7 11:06:10 1999
@@ -52,6 +52,22 @@
X struct sound_unit *next;
X };
X
+#ifdef CONFIG_SOUND_SONICVIBES
+extern int init_sonicvibes(void);
+#endif
+#ifdef CONFIG_SOUND_ES1370
+extern int init_es1370(void);
+#endif
+#ifdef CONFIG_SOUND_ES1371
+extern int init_es1371(void);
+#endif
+#ifdef CONFIG_SOUND_MSNDCLAS
+extern int msnd_classic_init(void);
+#endif
+#ifdef CONFIG_SOUND_MSNDPIN
+extern int msnd_pinnacle_init(void);
+#endif
+
X /*
X * Low level list operator. Scan the ordered list, find a hole and
X * join into it. Called with the lock asserted
@@ -132,7 +148,7 @@
X * This lock guards the sound loader list.
X */
X
-static spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
X
X /*
X * Allocate the controlling structure and add it to the sound driver
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/CREDITS linux/drivers/usb/CREDITS
--- v2.3.5/linux/drivers/usb/CREDITS Tue May 11 10:04:03 1999
+++ linux/drivers/usb/CREDITS Tue Jun 8 10:52:26 1999
@@ -8,6 +8,7 @@
X Johannes Erdfelt <jerd...@sventech.com>
X ham <h...@unsuave.com>
X Bradley M Keryan <ker...@andrew.cmu.edu>
+ Paul Mackerras <pau...@cs.anu.edu.au>
X Vojtech Pavlik <voj...@twilight.ucw.cz>
X Gregory P. Smith <gr...@electricrain.com>
X Linus Torvalds <torv...@transmeta.com>
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.5/linux/drivers/usb/Config.in Mon May 31 22:28:06 1999
+++ linux/drivers/usb/Config.in Mon Jun 7 20:04:01 1999
@@ -29,7 +29,11 @@
X dep_tristate 'USB keyboard support' CONFIG_USB_KBD $CONFIG_USB
X dep_tristate 'USB audio parsing support' CONFIG_USB_AUDIO $CONFIG_USB
X dep_tristate 'USB Abstract Control Model support' CONFIG_USB_ACM $CONFIG_USB
- dep_tristate 'Preliminary USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+ dep_tristate 'USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+ dep_tristate 'USB SCSI Support' CONFIG_USB_SCSI $CONFIG_USB
+ if [ "$CONFIG_USB_SCSI" != "n" ]; then
+ dep_tristate ' USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG $CONFIG_USB_SCSI
+ fi


X fi
X
X endmenu

diff -u --recursive --new-file v2.3.5/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.5/linux/drivers/usb/Makefile Mon May 31 22:28:06 1999
+++ linux/drivers/usb/Makefile Tue Jun 8 10:52:26 1999
@@ -109,6 +109,13 @@
X MIX_OBJS += cpia.o
X endif
X
+ifeq ($(CONFIG_USB_SCSI),y)
+ L_OBJS += usb_scsi.o
+ ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
+ L_OBJS += usb_scsi_debug.o
+ endif
+endif
+
X include $(TOPDIR)/Rules.make
X
X keymap.o: keymap.c
@@ -116,8 +123,17 @@
X keymap.c: maps/serial.map maps/usb.map maps/fixup.map
X ./mkmap > $@
X
+keymap-mac.o: keymap-mac.c
+keymap-mac.c: maps/mac.map maps/usb.map
+ ./mkmap.adb > $@
+
+ifneq ($(CONFIG_MAC_KEYBOARD),y)
X usb-keyboard.o: keymap.o keyboard.o
X $(LD) $(LD_RFLAG) -r -o $@ keymap.o keyboard.o
+else
+usb-keyboard.o: keymap-mac.o keyboard.o
+ $(LD) $(LD_RFLAG) -r -o $@ keymap-mac.o keyboard.o
+endif
X
X usb-uhci.o: uhci.o uhci-debug.o
X $(LD) $(LD_RFLAG) -r -o $@ uhci.o uhci-debug.o
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/README.ohci linux/drivers/usb/README.ohci
--- v2.3.5/linux/drivers/usb/README.ohci Mon May 17 09:55:22 1999
+++ linux/drivers/usb/README.ohci Tue Jun 8 10:52:26 1999
@@ -1,3 +1,9 @@
+June 08, 1999 01:23:34
+
+Paul Mackerras went through the OHCI (& USB code) to fix most of the
+endianness issues so that the code now works on Linux-PPC. He also
+simplified add_td_to_ed to be simpler & atomic to the hardware.
+
X May 16, 1999 16:20:54
X
X EDs are now allocated dynamically from their device's pool. Root hub
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.5/linux/drivers/usb/acm.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/acm.c Fri Jun 4 13:33:43 1999
@@ -198,7 +198,7 @@
X /*Now scan all configs for a ACM configuration*/
X for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
X /* The first one should be Communications interface? */
- interface = &dev->config[cfgnum].interface[0];
+ interface = &dev->config[cfgnum].altsetting[0].interface[0];
X if (interface->bInterfaceClass != 2 ||
X interface->bInterfaceSubClass != 2 ||
X interface->bInterfaceProtocol != 1 ||
@@ -212,7 +212,7 @@
X continue;
X
X /* The second one should be a Data interface? */
- interface = &dev->config[cfgnum].interface[1];
+ interface = &dev->config[cfgnum].altsetting[0].interface[1];
X if (interface->bInterfaceClass != 10 ||
X interface->bInterfaceSubClass != 0 ||
X interface->bInterfaceProtocol != 0 ||
@@ -234,12 +234,12 @@
X printk("USB ACM found\n");
X usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue);
X acm->dev=dev;
- acm->readendp=dev->config[cfgnum].interface[1].endpoint[0].bEndpointAddress;
- acm->writeendp=dev->config[cfgnum].interface[1].endpoint[1].bEndpointAddress;
- acm->ctrlendp=dev->config[cfgnum].interface[0].endpoint[0].bEndpointAddress;
+ acm->readendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].bEndpointAddress;
+ acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress;
+ acm->ctrlendp=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bEndpointAddress;
X acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
X acm->writepipe=usb_sndbulkpipe(dev,acm->writeendp);
- usb_request_irq(dev,acm->ctrlpipe=usb_rcvctrlpipe(dev,acm->ctrlendp), acm_irq, dev->config[cfgnum].interface[0].endpoint[0].bInterval, &acm->ctrlbuffer);
+ usb_request_irq(dev,acm->ctrlpipe=usb_rcvctrlpipe(dev,acm->ctrlendp), acm_irq, dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bInterval, &acm->ctrlbuffer);
X acm->present = 1;
X acm->buffer=0;
X return 0;
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.5/linux/drivers/usb/audio.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/audio.c Fri Jun 4 13:33:43 1999
@@ -42,7 +42,7 @@
X int i;
X int na=0;
X
- interface = &dev->config[0].interface[0];
+ interface = &dev->config[0].altsetting[0].interface[0];
X
X for(i=0;i<dev->config[0].bNumInterfaces;i++)
X {
@@ -133,7 +133,7 @@
X return usb_audio_init();
X }
X
-void module_cleanup(void)
+void cleanup_module(void)
X {
X usb_deregister(&usb_audio_driver);
X }
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- v2.3.5/linux/drivers/usb/cpia.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/cpia.c Fri Jun 4 13:33:43 1999
@@ -1164,7 +1164,7 @@
X return -1;
X #endif
X
- interface = &dev->config[0].interface[0];
+ interface = &dev->config[0].altsetting[0].interface[0];
X
X /* Is it a CPiA? */
X /*
@@ -1260,7 +1260,7 @@
X {
X return usb_cpia_init();
X }
-void module_cleanup(void)
+void cleanup_module(void)
X {
X }
X #endif
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.5/linux/drivers/usb/hub.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/hub.c Tue Jun 8 10:52:26 1999
@@ -159,7 +159,7 @@
X if (dev->config[0].bNumInterfaces != 1)
X return -1;
X
- interface = &dev->config[0].interface[0];
+ interface = &dev->config[0].altsetting[0].interface[0];
X
X /* Is it a hub? */
X if (interface->bInterfaceClass != 9)
@@ -241,8 +241,8 @@
X return;
X }
X
- portstatus = *((unsigned short *)buf + 0);
- portchange = *((unsigned short *)buf + 1);
+ portstatus = le16_to_cpup((unsigned short *)buf + 0);
+ portchange = le16_to_cpup((unsigned short *)buf + 1);
X
X if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
X (!(portstatus & USB_PORT_STAT_ENABLE))) {
@@ -294,8 +294,8 @@
X continue;
X }
X
- portstatus = *((unsigned short *)buf + 0);
- portchange = *((unsigned short *)buf + 1);
+ portstatus = le16_to_cpup((unsigned short *)buf + 0);
+ portchange = le16_to_cpup((unsigned short *)buf + 1);
X
X if (portchange & USB_PORT_STAT_C_CONNECTION) {
X printk("hub: port %d connection change\n", i + 1);
@@ -421,7 +421,7 @@
X return usb_hub_init();
X }
X
-void module_cleanup(void){
+void cleanup_module(void){
X usb_hub_cleanup();
X }
X #endif
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/keyboard.c linux/drivers/usb/keyboard.c
--- v2.3.5/linux/drivers/usb/keyboard.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/keyboard.c Tue Jun 8 10:52:26 1999
@@ -56,10 +56,12 @@
X int scancode = (int) usb_kbd_map[key];
X if(scancode)
X {
+#ifndef CONFIG_MAC_KEYBOARD
X if(scancode & PCKBD_NEEDS_E0)
X {
X handle_scancode(0xe0, 1);
X }
+#endif /* CONFIG_MAC_KEYBOARD */
X handle_scancode((scancode & ~PCKBD_NEEDS_E0), down);
X }
X }
@@ -171,7 +173,10 @@
X struct usb_endpoint_descriptor *endpoint;
X struct usb_keyboard *kbd;
X
- interface = &dev->config[0].interface[0];
+ if (dev->descriptor.bNumConfigurations < 1)
+ return -1;
+
+ interface = &dev->config[0].altsetting[0].interface[0];
X endpoint = &interface->endpoint[0];
X
X if(interface->bInterfaceClass != 3
@@ -233,7 +238,7 @@
X return usb_kbd_init();
X }
X
-void module_cleanup(void)
+void cleanup_module(void)
X {
X usb_deregister(&usb_kbd_driver);
X }
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/keymap-mac.c linux/drivers/usb/keymap-mac.c
--- v2.3.5/linux/drivers/usb/keymap-mac.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/keymap-mac.c Tue Jun 8 10:52:26 1999
@@ -0,0 +1,50 @@
+unsigned char usb_kbd_map[256] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x0b, 0x08, 0x02,
+ 0x0e, 0x03, 0x05, 0x04, 0x22, 0x26, 0x28, 0x25,
+
+ 0x2e, 0x2d, 0x1f, 0x23, 0x0c, 0x0f, 0x01, 0x11,
+ 0x20, 0x09, 0x0d, 0x07, 0x10, 0x06, 0x12, 0x13,
+
+ 0x14, 0x15, 0x17, 0x16, 0x1a, 0x1c, 0x19, 0x1d,
+ 0x24, 0x35, 0x33, 0x30, 0x31, 0x1b, 0x18, 0x21,
+
+ 0x1e, 0x2a, 0x00, 0x29, 0x27, 0x32, 0x2b, 0x2f,
+ 0x2c, 0x39, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61,
+
+ 0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b,
+ 0x71, 0x72, 0x73, 0x74, 0x75, 0x77, 0x79, 0x3c,
+
+ 0x3b, 0x3d, 0x3e, 0x47, 0x4b, 0x43, 0x4e, 0x45,
+ 0x4c, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+
+ 0x5b, 0x5c, 0x52, 0x41, 0x00, 0x00, 0x00, 0x00,
+ 0x69, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0x38, 0x3a, 0x37, 0x7d, 0x7b, 0x7c, 0x37,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/maps/mac.map linux/drivers/usb/maps/mac.map
--- v2.3.5/linux/drivers/usb/maps/mac.map Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/maps/mac.map Tue Jun 8 10:52:26 1999
@@ -0,0 +1,350 @@
+# Kernel keymap for Macintoshes. This uses 7 modifier combinations.
+keymaps 0-2,4-5,8,12
+#
+# Fixups:
+keycode 0x69 = Print_Screen
+keycode 0x6b = F14
+keycode 0x37 = Window_R
+#
+#keycode 0x00 = a
+# hack!
+keycode 0x80 = a
+ altgr keycode 0x00 = Hex_A
+keycode 0x01 = s
+keycode 0x02 = d
+ altgr keycode 0x02 = Hex_D
+keycode 0x03 = f
+ altgr keycode 0x03 = Hex_F
+keycode 0x04 = h
+keycode 0x05 = g
+keycode 0x06 = z
+keycode 0x07 = x
+keycode 0x08 = c
+ altgr keycode 0x08 = Hex_C
+keycode 0x09 = v
+keycode 0x0a =
+keycode 0x0b = b
+ altgr keycode 0x0b = Hex_B
+keycode 0x0c = q
+keycode 0x0d = w
+keycode 0x0e = e
+ altgr keycode 0x0e = Hex_E
+keycode 0x0f = r
+keycode 0x10 = y
+keycode 0x11 = t
+keycode 0x12 = one exclam
+ alt keycode 0x12 = Meta_one
+keycode 0x13 = two at at
+ control keycode 0x13 = nul
+ shift control keycode 0x13 = nul
+ alt keycode 0x13 = Meta_two
+keycode 0x14 = three numbersign
+ control keycode 0x14 = Escape
+ alt keycode 0x14 = Meta_three
+keycode 0x15 = four dollar dollar
+ control keycode 0x15 = Control_backslash
+ alt keycode 0x15 = Meta_four
+keycode 0x16 = six asciicircum
+ control keycode 0x16 = Control_asciicircum
+ alt keycode 0x16 = Meta_six
+keycode 0x17 = five percent
+ control keycode 0x17 = Control_bracketright
+ alt keycode 0x17 = Meta_five
+keycode 0x18 = equal plus
+ alt keycode 0x18 = Meta_equal
+keycode 0x19 = nine parenleft bracketright
+ alt keycode 0x19 = Meta_nine
+keycode 0x1a = seven ampersand braceleft
+ control keycode 0x1a = Control_underscore
+ alt keycode 0x1a = Meta_seven
+keycode 0x1b = minus underscore backslash
+ control keycode 0x1b = Control_underscore
+ shift control keycode 0x1b = Control_underscore
+ alt keycode 0x1b = Meta_minus
+keycode 0x1c = eight asterisk bracketleft
+ control keycode 0x1c = Delete
+ alt keycode 0x1c = Meta_eight
+keycode 0x1d = zero parenright braceright
+ alt keycode 0x1d = Meta_zero
+keycode 0x1e = bracketright braceright asciitilde
+ control keycode 0x1e = Control_bracketright
+ alt keycode 0x1e = Meta_bracketright
+keycode 0x1f = o
+keycode 0x20 = u
+keycode 0x21 = bracketleft braceleft
+ control keycode 0x21 = Escape
+ alt keycode 0x21 = Meta_bracketleft
+keycode 0x22 = i
+keycode 0x23 = p
+keycode 0x24 = Return
+ alt keycode 0x24 = Meta_Control_m
+keycode 0x25 = l
+keycode 0x26 = j
+keycode 0x27 = apostrophe quotedbl
+ control keycode 0x27 = Control_g
+ alt keycode 0x27 = Meta_apostrophe
+keycode 0x28 = k
+keycode 0x29 = semicolon colon
+ alt keycode 0x29 = Meta_semicolon
+keycode 0x2a = backslash bar
+ control keycode 0x2a = Control_backslash
+ alt keycode 0x2a = Meta_backslash
+keycode 0x2b = comma less
+ alt keycode 0x2b = Meta_comma
+keycode 0x2c = slash question
+ control keycode 0x2c = Delete
+ alt keycode 0x2c = Meta_slash
+keycode 0x2d = n
+keycode 0x2e = m
+keycode 0x2f = period greater
+ control keycode 0x2f = Compose
+ alt keycode 0x2f = Meta_period
+keycode 0x30 = Tab Tab
+ alt keycode 0x30 = Meta_Tab
+keycode 0x31 = space space
+ control keycode 0x31 = nul
+ alt keycode 0x31 = Meta_space
+keycode 0x32 = grave asciitilde
+ control keycode 0x32 = nul
+ alt keycode 0x32 = Meta_grave
+keycode 0x33 = Delete Delete
+ control keycode 0x33 = BackSpace
+ alt keycode 0x33 = Meta_Delete
+keycode 0x34 =
+keycode 0x35 = Escape Escape
+ alt keycode 0x35 = Meta_Escape
+keycode 0x36 = Control
+keycode 0x37 = Window
+keycode 0x38 = Shift
+keycode 0x39 = Caps_Lock
+keycode 0x3a = Alt
+keycode 0x3b = Left
+ alt keycode 0x3b = Decr_Console
+keycode 0x3c = Right
+ alt keycode 0x3c = Incr_Console
+keycode 0x3d = Down
+keycode 0x3e = Up
+keycode 0x3f =
+keycode 0x40 =
+keycode 0x41 = KP_Period
+keycode 0x42 =
+keycode 0x43 = KP_Multiply
+keycode 0x44 =
+keycode 0x45 = KP_Add
+keycode 0x46 =
+keycode 0x47 = Num_Lock
+# shift keycode 0x47 = Bare_Num_Lock
+keycode 0x48 =
+keycode 0x49 =
+keycode 0x4a =
+keycode 0x4b = KP_Divide
+keycode 0x4c = KP_Enter
+keycode 0x4d =
+keycode 0x4e = KP_Subtract
+keycode 0x4f =
+keycode 0x50 =
+keycode 0x51 =
+#keycode 0x51 = KP_Equals
+keycode 0x52 = KP_0
+ alt keycode 0x52 = Ascii_0
+ altgr keycode 0x52 = Hex_0
+keycode 0x53 = KP_1
+ alt keycode 0x53 = Ascii_1
+ altgr keycode 0x53 = Hex_1
+keycode 0x54 = KP_2
+ alt keycode 0x54 = Ascii_2
+ altgr keycode 0x54 = Hex_2
+keycode 0x55 = KP_3
+ alt keycode 0x55 = Ascii_3
+ altgr keycode 0x55 = Hex_3
+keycode 0x56 = KP_4
+ alt keycode 0x56 = Ascii_4
+ altgr keycode 0x56 = Hex_4
+keycode 0x57 = KP_5
+ alt keycode 0x57 = Ascii_5
+ altgr keycode 0x57 = Hex_5
+keycode 0x58 = KP_6
+ alt keycode 0x58 = Ascii_6
+ altgr keycode 0x58 = Hex_6
+keycode 0x59 = KP_7
+ alt keycode 0x59 = Ascii_7
+ altgr keycode 0x59 = Hex_7
+keycode 0x5b = KP_8
+ alt keycode 0x5b = Ascii_8
+ altgr keycode 0x5b = Hex_8
+keycode 0x5c = KP_9
+ alt keycode 0x5c = Ascii_9
+ altgr keycode 0x5c = Hex_9
+keycode 0x5d =
+keycode 0x5e =
+keycode 0x5f =
+keycode 0x60 = F5 F15 Console_17
+ control keycode 0x60 = F5
+ alt keycode 0x60 = Console_5
+ control alt keycode 0x60 = Console_5
+keycode 0x61 = F6 F16 Console_18
+ control keycode 0x61 = F6
+ alt keycode 0x61 = Console_6
+ control alt keycode 0x61 = Console_6
+keycode 0x62 = F7 F17 Console_19
+ control keycode 0x62 = F7
+ alt keycode 0x62 = Console_7
+ control alt keycode 0x62 = Console_7
+keycode 0x63 = F3 F13 Console_15
+ control keycode 0x63 = F3
+ alt keycode 0x63 = Console_3
+ control alt keycode 0x63 = Console_3
+keycode 0x64 = F8 F18 Console_20
+ control keycode 0x64 = F8
+ alt keycode 0x64 = Console_8
+ control alt keycode 0x64 = Console_8
+keycode 0x65 = F9 F19 Console_21
+ control keycode 0x65 = F9
+ alt keycode 0x65 = Console_9
+ control alt keycode 0x65 = Console_9
+keycode 0x66 =
+keycode 0x67 = F11 F11 Console_23
+ control keycode 0x67 = F11
+ alt keycode 0x67 = Console_11
+ control alt keycode 0x67 = Console_11
+keycode 0x68 =
+keycode 0x69 = F13
+keycode 0x6a =
+keycode 0x6b = Scroll_Lock Show_Memory Show_Registers
+ control keycode 0x6b = Show_State
+ alt keycode 0x6b = Scroll_Lock
+keycode 0x6c =
+keycode 0x6d = F10 F20 Console_22
+ control keycode 0x6d = F10
+ alt keycode 0x6d = Console_10
+ control alt keycode 0x6d = Console_10
+keycode 0x6e =
+keycode 0x6f = F12 F12 Console_24
+ control keycode 0x6f = F12
+ alt keycode 0x6f = Console_12
+ control alt keycode 0x6f = Console_12
+keycode 0x70 =
+keycode 0x71 = Pause
+keycode 0x72 = Insert
+keycode 0x73 = Home
+keycode 0x74 = Prior
+ shift keycode 0x74 = Scroll_Backward
+keycode 0x75 = Remove
+keycode 0x76 = F4 F14 Console_16
+ control keycode 0x76 = F4
+ alt keycode 0x76 = Console_4
+ control alt keycode 0x76 = Console_4
+keycode 0x77 = End
+keycode 0x78 = F2 F12 Console_14
+ control keycode 0x78 = F2
+ alt keycode 0x78 = Console_2
+ control alt keycode 0x78 = Console_2
+keycode 0x79 = Next
+ shift keycode 0x79 = Scroll_Forward
+keycode 0x7a = F1 F11 Console_13
+ control keycode 0x7a = F1
+ alt keycode 0x7a = Console_1
+ control alt keycode 0x7a = Console_1
+keycode 0x7b = Shift_R
+keycode 0x7c = Alt_R
+keycode 0x7d = Control_R
+keycode 0x7e =
+keycode 0x7f =
+#keycode 0x7f = Power
+ control shift keycode 0x7f = Boot
+string F1 = "\033[[A"
+string F2 = "\033[[B"
+string F3 = "\033[[C"
+string F4 = "\033[[D"
+string F5 = "\033[[E"
+string F6 = "\033[17~"
+string F7 = "\033[18~"
+string F8 = "\033[19~"
+string F9 = "\033[20~"
+string F10 = "\033[21~"
+string F11 = "\033[23~"
+string F12 = "\033[24~"
+string F13 = "\033[25~"
+string F14 = "\033[26~"
+string F15 = "\033[28~"
+string F16 = "\033[29~"
+string F17 = "\033[31~"
+string F18 = "\033[32~"
+string F19 = "\033[33~"
+string F20 = "\033[34~"
+string Find = "\033[1~"
+string Insert = "\033[2~"
+string Remove = "\033[3~"
+string Select = "\033[4~"
+string Prior = "\033[5~"
+string Next = "\033[6~"
+string Macro = "\033[M"
+string Pause = "\033[P"
+compose '`' 'A' to 'À'
+compose '`' 'a' to 'à'
+compose '\'' 'A' to 'Á'
+compose '\'' 'a' to 'á'
+compose '^' 'A' to 'Â'
+compose '^' 'a' to 'â'
+compose '~' 'A' to 'Ã'
+compose '~' 'a' to 'ã'
+compose '"' 'A' to 'Ä'
+compose '"' 'a' to 'ä'
+compose 'O' 'A' to 'Å'
+compose 'o' 'a' to 'å'
+compose '0' 'A' to 'Å'
+compose '0' 'a' to 'å'
+compose 'A' 'A' to 'Å'
+compose 'a' 'a' to 'å'
+compose 'A' 'E' to 'Æ'
+compose 'a' 'e' to 'æ'
+compose ',' 'C' to 'Ç'
+compose ',' 'c' to 'ç'
+compose '`' 'E' to 'È'
+compose '`' 'e' to 'è'
+compose '\'' 'E' to 'É'
+compose '\'' 'e' to 'é'
+compose '^' 'E' to 'Ê'
+compose '^' 'e' to 'ê'
+compose '"' 'E' to 'Ë'
+compose '"' 'e' to 'ë'
+compose '`' 'I' to 'Ì'
+compose '`' 'i' to 'ì'
+compose '\'' 'I' to 'Í'
+compose '\'' 'i' to 'í'
+compose '^' 'I' to 'Î'
+compose '^' 'i' to 'î'
+compose '"' 'I' to 'Ï'
+compose '"' 'i' to 'ï'
+compose '-' 'D' to 'Ð'
+compose '-' 'd' to 'ð'
+compose '~' 'N' to 'Ñ'
+compose '~' 'n' to 'ñ'
+compose '`' 'O' to 'Ò'
+compose '`' 'o' to 'ò'
+compose '\'' 'O' to 'Ó'
+compose '\'' 'o' to 'ó'
+compose '^' 'O' to 'Ô'
+compose '^' 'o' to 'ô'
+compose '~' 'O' to 'Õ'
+compose '~' 'o' to 'õ'
+compose '"' 'O' to 'Ö'
+compose '"' 'o' to 'ö'
+compose '/' 'O' to 'Ø'
+compose '/' 'o' to 'ø'
+compose '`' 'U' to 'Ù'
+compose '`' 'u' to 'ù'
+compose '\'' 'U' to 'Ú'
+compose '\'' 'u' to 'ú'
+compose '^' 'U' to 'Û'
+compose '^' 'u' to 'û'
+compose '"' 'U' to 'Ü'
+compose '"' 'u' to 'ü'
+compose '\'' 'Y' to 'Ý'
+compose '\'' 'y' to 'ý'
+compose 'T' 'H' to 'Þ'
+compose 't' 'h' to 'þ'
+compose 's' 's' to 'ß'
+compose '"' 'y' to 'ÿ'
+compose 's' 'z' to 'ß'
+compose 'i' 'j' to 'ÿ'
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/mkmap.adb linux/drivers/usb/mkmap.adb
--- v2.3.5/linux/drivers/usb/mkmap.adb Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/mkmap.adb Tue Jun 8 10:52:26 1999
@@ -0,0 +1,88 @@
+#!/usr/bin/perl
+
+($ME = $0) =~ s|.*/||;
+
+$file = "maps/mac.map";
+$line = 1;
+open(PC, $file) || die("$!");
+while(<PC>)
+{
+ if(/^\s*keycode\s+(\d+|0x[0-9a-fA-F]+)\s*=\s*(\S+)/)
+ {
+ my($idx) = $1;
+ my($sym) = $2;
+ if ($idx =~ "0x.*") {
+ $idx = hex($idx);
+ } else {
+ $idx = int($idx);
+ }
+ if(defined($map{uc($sym)}))
+ {
+ # print STDERR "$file:$line: warning: `$sym' redefined\n";
+ }
+ $map{uc($sym)} = $idx;
+ }
+ $line++;
+}
+close(PC);
+
+# $file = "maps/fixup.map";
+# $line = 1;
+# open(FIXUP, $file) || die("$!");
+# while(<FIXUP>)
+# {
+# if(/^\s*keycode\s+(\d+)\s*=\s*/)
+# {
+# my($idx) = int($1);
+# for $sym (split(/\s+/, $'))
+# {
+# $map{uc($sym)} = $idx;
+# }
+# }
+# $line++;
+# }
+# close(FIXUP);
+
+$file = "maps/usb.map";
+$line = 1;
+open(USB, $file) || die("$!");
+while(<USB>)
+{
+ if(/^\s*keycode\s+(\d+)\s*=\s*/)
+ {
+ my($idx) = int($1);
+ for $sym (split(/\s+/, $'))
+ {
+ my($val) = $map{uc($sym)};
+ $map[$idx] = $val;
+ if(!defined($val))
+ {
+ print STDERR "$file:$line: warning: `$sym' undefined\n";
+ }
+ else
+ {
+ last;
+ }
+ }
+ }
+ $line++;
+}
+close(USB);
+
+print "unsigned char usb_kbd_map[256] = \n{\n";
+for($x = 0; $x < 32; $x++)
+{
+ if($x && !($x % 2))
+ {
+ print "\n";
+ }
+ print " ";
+ for($y = 0; $y < 8; $y++)
+ {
+ my($idx) = $x * 8 + $y;
+ print sprintf(" 0x%02x,",
+ int(defined($map[$idx]) ? $map[$idx]:0));
+ }
+ print "\n";
+}
+print "};\n";
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c
--- v2.3.5/linux/drivers/usb/mouse.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/mouse.c Mon Jun 7 13:36:40 1999
@@ -75,7 +75,7 @@
X mouse->buttons = data[0] & 0x07;
X mouse->dx += data[1]; /* data[] is signed, so this works */
X mouse->dy -= data[2]; /* y-axis is reversed */
- mouse->dz += data[3];
+ mouse->dz -= data[3];
X mouse->ready = 1;
X
X add_mouse_randomness((mouse->buttons << 24) + (mouse->dz << 16 ) +
@@ -249,7 +249,7 @@
X return -1;
X
X /* Is it a mouse interface? */
- interface = &dev->config[0].interface[0];
+ interface = &dev->config[0].altsetting[0].interface[0];
X if (interface->bInterfaceClass != 3)
X return -1;
X if (interface->bInterfaceSubClass != 1)
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/ohci-debug.c linux/drivers/usb/ohci-debug.c
--- v2.3.5/linux/drivers/usb/ohci-debug.c Mon May 17 09:55:22 1999
+++ linux/drivers/usb/ohci-debug.c Tue Jun 8 10:52:26 1999
@@ -67,7 +67,7 @@
X
X void show_ohci_ed(struct ohci_ed *ed)
X {
- int stat = ed->status;
+ int stat = le32_to_cpup(&ed->status);
X int skip = (stat & OHCI_ED_SKIP);
X int mps = (stat & OHCI_ED_MPS) >> 16;
X int isoc = (stat & OHCI_ED_F_ISOC);
@@ -75,8 +75,8 @@
X int dir = (stat & OHCI_ED_D);
X int endnum = (stat & OHCI_ED_EN) >> 7;
X int funcaddr = (stat & OHCI_ED_FA);
- int halted = (ed->_head_td & 1);
- int toggle = (ed->_head_td & 2) >> 1;
+ int halted = (le32_to_cpup(&ed->_head_td) & 1);
+ int toggle = (le32_to_cpup(&ed->_head_td) & 2) >> 1;
X
X printk(KERN_DEBUG " ohci ED:\n");
X printk(KERN_DEBUG " status = 0x%x\n", stat);
@@ -92,23 +92,24 @@
X endnum,
X funcaddr,
X (stat & ED_ALLOCATED) ? " Allocated" : "");
- printk(KERN_DEBUG " tail_td = 0x%x\n", ed->tail_td);
+ printk(KERN_DEBUG " tail_td = 0x%x\n", ed_tail_td(ed));
X printk(KERN_DEBUG " head_td = 0x%x\n", ed_head_td(ed));
- printk(KERN_DEBUG " next_ed = 0x%x\n", ed->next_ed);
+ printk(KERN_DEBUG " next_ed = 0x%x\n", le32_to_cpup(&ed->next_ed));
X } /* show_ohci_ed() */
X
X
X void show_ohci_td(struct ohci_td *td)
X {
- int td_round = td->info & OHCI_TD_ROUND;
- int td_dir = td->info & OHCI_TD_D;
- int td_int_delay = (td->info & OHCI_TD_IOC_DELAY) >> 21;
- int td_toggle = (td->info & OHCI_TD_DT) >> 24;
+ int info = le32_to_cpup(&td->info);
+ int td_round = info & OHCI_TD_ROUND;
+ int td_dir = info & OHCI_TD_D;
+ int td_int_delay = (info & OHCI_TD_IOC_DELAY) >> 21;
+ int td_toggle = (info & OHCI_TD_DT) >> 24;
X int td_errcnt = td_errorcount(*td);
- int td_cc = OHCI_TD_CC_GET(td->info);
+ int td_cc = OHCI_TD_CC_GET(info);
X
X printk(KERN_DEBUG " ohci TD hardware fields:\n");
- printk(KERN_DEBUG " info = 0x%x\n", td->info);
+ printk(KERN_DEBUG " info = 0x%x\n", info);
X printk(KERN_DEBUG " %s%s%s%d %s %s%d\n",
X td_round ? "Rounding " : "",
X (td_dir == OHCI_TD_D_IN) ? "Input " :
@@ -125,9 +126,9 @@
X
X printk(KERN_DEBUG " %s\n", td_allocated(*td) ? "Allocated" : "Free");
X
- printk(KERN_DEBUG " cur_buf = 0x%x\n", td->cur_buf);
- printk(KERN_DEBUG " next_td = 0x%x\n", td->next_td);
- printk(KERN_DEBUG " buf_end = 0x%x\n", td->buf_end);
+ printk(KERN_DEBUG " cur_buf = 0x%x\n", le32_to_cpup(&td->cur_buf));
+ printk(KERN_DEBUG " next_td = 0x%x\n", le32_to_cpup(&td->next_td));
+ printk(KERN_DEBUG " buf_end = 0x%x\n", le32_to_cpup(&td->buf_end));
X printk(KERN_DEBUG " ohci TD driver fields:\n");
X printk(KERN_DEBUG " data = %p\n", td->data);
X printk(KERN_DEBUG " dev_id = %p\n", td->dev_id);
@@ -169,11 +170,14 @@
X printk(KERN_DEBUG " ohci_hcca\n");
X
X for (idx=0; idx<NUM_INTS; idx++) {
- printk(KERN_DEBUG " int_table[%2d] == %p\n", idx, hcca->int_table +idx);
+ printk(KERN_DEBUG " int_table[%2d] == %x\n", idx,
+ le32_to_cpup(hcca->int_table + idx));
X }
X
- printk(KERN_DEBUG " frame_no == %d\n", hcca->frame_no);
- printk(KERN_DEBUG " donehead == 0x%08x\n", hcca->donehead);
+ printk(KERN_DEBUG " frame_no == %d\n",
+ le16_to_cpup(&hcca->frame_no));
+ printk(KERN_DEBUG " donehead == 0x%08x\n",
+ le32_to_cpup(&hcca->donehead));
X } /* show_ohci_hcca() */
X
X
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
--- v2.3.5/linux/drivers/usb/ohci.c Mon May 31 22:28:06 1999
+++ linux/drivers/usb/ohci.c Tue Jun 8 10:52:26 1999
@@ -71,60 +71,84 @@
X
X static spinlock_t ohci_edtd_lock = SPIN_LOCK_UNLOCKED;
X
+#define FIELDS_OF_ED(e) le32_to_cpup(&e->status), le32_to_cpup(&e->tail_td), \
+ le32_to_cpup(&e->_head_td), le32_to_cpup(&e->next_ed)
+#define FIELDS_OF_TD(t) le32_to_cpup(&t->info), le32_to_cpup(&t->cur_buf), \
+ le32_to_cpup(&t->next_td), le32_to_cpup(&t->buf_end)
+
+static const char *cc_names[16] = {
+ "no error",
+ "CRC error",
+ "bit stuff error",
+ "data toggle mismatch",
+ "stall",
+ "device not responding",
+ "PID check failed",
+ "unexpected PID",
+ "data overrun",
+ "data underrun",
+ "reserved (10)",
+ "reserved (11)",
+ "buffer overrun",
+ "buffer underrun",
+ "not accessed (14)",
+ "not accessed"
+};
+
X /*
- * Add a TD to the end of the TD list on a given ED. This function
- * does NOT advance the ED's tail_td pointer beyond the given TD. To
- * add multiple TDs, call this function once for each TD. Do not
- * "simply" update tail_td yourself... This function does more than
- * that.
- *
- * If this ED is on the controller, you MUST set its SKIP flag before
- * calling this function.
+ * Add a chain of TDs to the end of the TD list on a given ED.
+ *
+ * This function uses the first TD of the chain as the new dummy TD
+ * for the ED, and uses the old dummy TD instead of the first TD
+ * of the chain. The reason for this is that this makes it possible
+ * to update the TD chain without needing any locking between the
+ * CPU and the OHCI controller.
X *
- * Important! This function needs locking and atomicity as it works
- * in parallel with the HC's DMA. Locking ohci_edtd_lock while using
- * the function is a must.
+ * The return value is the pointer to the new first TD (the old
+ * dummy TD).
+ *
+ * Important! This function is not re-entrant w.r.t. each ED.
+ * Locking ohci_edtd_lock while using the function is a must
+ * if there is any possibility of another CPU or an interrupt routine
+ * calling this function with the same ED.
X *
X * This function can be called by the interrupt handler.
X */
-static void ohci_add_td_to_ed(struct ohci_td *td, struct ohci_ed *ed)
+static struct ohci_td *ohci_add_td_to_ed(struct ohci_td *td,
+ struct ohci_td *last_td, struct ohci_ed *ed)
X {
- struct ohci_td *dummy_td, *prev_td;
+ struct ohci_td *t, *dummy_td;
+ u32 new_dummy;
X
X if (ed->tail_td == 0) {
X printk("eek! an ED without a dummy_td\n");
+ return td;
X }
X
- /* The ED's tail_td is constant, always pointing to the
- * dummy_td. The reason the ED never processes the dummy is
- * that it stops processing TDs as soon as head_td == tail_td.
- * When it advances to this last dummy TD it conveniently stops. */
- dummy_td = bus_to_virt(ed->tail_td);
-
- /* Dummy's data pointer is used to point to the previous TD */
- if (ed_head_td(ed) != ed->tail_td) {
- prev_td = (struct ohci_td *) dummy_td->data;
- } else {
- /* if the ED is empty, previous is meaningless */
- /* We'll be inserting into the head of the list */
- prev_td = NULL;
- }
-
- /* Store the new back pointer and set up this TD's next */
- dummy_td->data = td;
- td->next_td = ed->tail_td;
-
- /* Store the TD pointer back to the ED */
- td->ed = ed;
-
- if (!prev_td) { /* No previous TD? then insert us at the head */
- if (ed_head_td(ed) != ed->tail_td)
- printk(KERN_DEBUG "Suspicious ED...\n");
- set_ed_head_td(ed, virt_to_bus(td)); /* put it on the ED */
- } else {
- /* add the TD to the end */
- prev_td->next_td = virt_to_bus(td);
+ /* Get a pointer to the current dummy TD. */
+ dummy_td = bus_to_virt(ed_tail_td(ed));
+
+ for (t = td; ; t = bus_to_virt(le32_to_cpup(&t->next_td))) {
+ t->ed = ed;
+ if (t == last_td)
+ break;
X }
+
+ /* Make the last TD point back to the first, since it
+ * will become the new dummy TD. */
+ new_dummy = cpu_to_le32(virt_to_bus(td));
+ last_td->next_td = new_dummy;
+
+ /* Copy the contents of the first TD into the dummy */
+ *dummy_td = *td;
+
+ /* Turn the first TD into a dummy */
+ make_dumb_td(td);
+
+ /* Set the HC's tail pointer to the new dummy */
+ ed->tail_td = new_dummy;
+
+ return dummy_td; /* replacement head of chain */
X } /* ohci_add_td_to_ed() */
X
X
@@ -169,9 +193,7 @@
X
X /* if the list is not empty, insert this ED at the front */
X /* XXX should they go on the end? */
- if (listhead) {
- ed->next_ed = listhead;
- }
+ ed->next_ed = cpu_to_le32(listhead);
X
X /* update the hardware listhead pointer */
X writel(virt_to_bus(ed), hw_listhead_p);
@@ -221,7 +243,7 @@
X * Insert this ED at the front of the list.
X */
X ed->next_ed = int_ed->next_ed;
- int_ed->next_ed = virt_to_bus(ed);
+ int_ed->next_ed = cpu_to_le32(virt_to_bus(ed));
X
X spin_unlock_irqrestore(&ohci_edtd_lock, flags);
X
@@ -249,21 +271,21 @@
X */
X void ohci_wait_for_ed_safe(struct ohci_regs *regs, struct ohci_ed *ed, int ed_type)
X {
- __u32 hw_listcurrent;
+ __u32 *hw_listcurrent;
X
X /* tell the controller to skip this ED */
- ed->status |= OHCI_ED_SKIP;
+ ed->status |= cpu_to_le32(OHCI_ED_SKIP);
X
X switch (ed_type) {
X case HCD_ED_CONTROL:
- hw_listcurrent = readl(regs->ed_controlcurrent);
+ hw_listcurrent = &regs->ed_controlcurrent;
X break;
X case HCD_ED_BULK:
- hw_listcurrent = readl(regs->ed_bulkcurrent);
+ hw_listcurrent = &regs->ed_bulkcurrent;
X break;
X case HCD_ED_ISOC:
X case HCD_ED_INT:
- hw_listcurrent = readl(regs->ed_periodcurrent);
+ hw_listcurrent = &regs->ed_periodcurrent;
X break;
X default:
X return;
@@ -273,11 +295,11 @@
X * If the HC is processing this ED we need to wait until the
X * at least the next frame.
X */
- if (virt_to_bus(ed) == hw_listcurrent) {
+ if (virt_to_bus(ed) == readl(hw_listcurrent)) {
X DECLARE_WAITQUEUE(wait, current);
X
X #ifdef OHCI_DEBUG
- printk("Waiting a frame for OHC to finish with ED %p\n", ed);
+ printk("Waiting a frame for OHC to finish with ED %p [%x %x %x %x]\n", ed, FIELDS_OF_ED(ed));
X #endif
X
X add_wait_queue(&start_of_frame_wakeup, &wait);
@@ -349,7 +371,7 @@
X /* walk the list and unlink the ED if found */
X do {
X prev = cur;
- cur = bus_to_virt(cur->next_ed);
+ cur = bus_to_virt(le32_to_cpup(&cur->next_ed));
X
X if (virt_to_bus(cur) == bus_ed) {
X /* unlink from the list */
@@ -401,7 +423,7 @@
X return;
X
X /* set the "skip me bit" in this ED */
- ed->status |= OHCI_ED_SKIP;
+ ed->status |= cpu_to_le32(OHCI_ED_SKIP);
X
X /* XXX Assuming this list will never be circular */
X
@@ -415,7 +437,7 @@
X /* FIXME: collapse this into a nice simple loop :) */
X if (head_td->next_td != 0) {
X prev_td = head_td;
- cur_td = bus_to_virt(head_td->next_td);
+ cur_td = bus_to_virt(le32_to_cpup(&head_td->next_td));
X for (;;) {
X if (td == cur_td) {
X /* remove it */
@@ -425,7 +447,7 @@
X if (cur_td->next_td == 0)
X break;
X prev_td = cur_td;
- cur_td = bus_to_virt(cur_td->next_td);
+ cur_td = bus_to_virt(le32_to_cpup(&cur_td->next_td));
X }
X }
X }
@@ -437,7 +459,7 @@
X ohci_free_td(td);
X
X /* unset the "skip me bit" in this ED */
- ed->status &= ~OHCI_ED_SKIP;
+ ed->status &= cpu_to_le32(~OHCI_ED_SKIP);
X
X spin_unlock_irqrestore(&ohci_edtd_lock, flags);
X } /* ohci_remove_td_from_ed() */
@@ -465,7 +487,7 @@
X /* zero out the TD */
X memset(new_td, 0, sizeof(*new_td));
X /* mark the new TDs as unaccessed */
- new_td->info = OHCI_TD_CC_NEW;
+ new_td->info = cpu_to_le32(OHCI_TD_CC_NEW);
X /* mark it as allocated */
X allocate_td(new_td);
X return new_td;
@@ -492,7 +514,7 @@
X /* zero out the ED */
X memset(new_ed, 0, sizeof(*new_ed));
X /* all new EDs start with the SKIP bit set */
- new_ed->status |= OHCI_ED_SKIP;
+ new_ed->status |= cpu_to_le32(OHCI_ED_SKIP);
X /* mark it as allocated */
X allocate_ed(new_ed);
X return new_ed;
@@ -509,12 +531,21 @@
X if (!ed)
X return;
X
- if (ed->tail_td == 0) {
- printk("yikes! an ED without a dummy_td\n");
- } else
- ohci_free_td((struct ohci_td *)bus_to_virt(ed->tail_td));
+ if (ed_head_td(ed) != 0) {
+ struct ohci_td *td, *tail_td, *next_td;
X
- ed->status &= ~(__u32)ED_ALLOCATED;
+ td = bus_to_virt(ed_head_td(ed));
+ tail_td = bus_to_virt(ed_tail_td(ed));
+ for (;;) {
+ next_td = bus_to_virt(le32_to_cpup(&td->next_td));
+ ohci_free_td(td);
+ if (td == tail_td)
+ break;
+ td = next_td;
+ }
+ }
+
+ ed->status &= cpu_to_le32(~(__u32)ED_ALLOCATED);
X } /* ohci_free_ed() */
X
X
@@ -527,12 +558,13 @@
X inline struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
X {
X /* hardware fields */
- td->info = OHCI_TD_CC_NEW |
- (dir & OHCI_TD_D) |
- (toggle & OHCI_TD_DT) |
- flags;
- td->cur_buf = (data == NULL) ? 0 : virt_to_bus(data);
- td->buf_end = (len == 0) ? 0 : td->cur_buf + len - 1;
+ td->info = cpu_to_le32(OHCI_TD_CC_NEW |
+ (dir & OHCI_TD_D) |
+ (toggle & OHCI_TD_DT) |
+ flags);
+ td->cur_buf = (data == NULL) ? 0 : cpu_to_le32(virt_to_bus(data));
+ td->buf_end = (len == 0) ? 0 :
+ cpu_to_le32(le32_to_cpup(&td->cur_buf) + len - 1);
X
X /* driver fields */
X td->data = data;
@@ -555,11 +587,13 @@
X * not be any!). This assumes that the ED is Allocated and will
X * force the Allocated bit on.
X */
-struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed, int maxpacketsize, int lowspeed, int endp_id, int isoc_tds)
+struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed,
+ int maxpacketsize, int lowspeed, int endp_id,
+ int isoc_tds)
X {
X struct ohci_td *dummy_td;
X
- if (ed_head_td(ed) != ed->tail_td)
+ if (ed_head_td(ed) != ed_tail_td(ed))
X printk("Reusing a non-empty ED %p!\n", ed);
X
X if (!ed->tail_td) {
@@ -569,9 +603,9 @@
X return NULL; /* no dummy available! */
X }
X make_dumb_td(dummy_td); /* flag it as a dummy */
- ed->tail_td = virt_to_bus(dummy_td);
+ ed->tail_td = cpu_to_le32(virt_to_bus(dummy_td));
X } else {
- dummy_td = bus_to_virt(ed->tail_td);
+ dummy_td = bus_to_virt(ed_tail_td(ed));
X if (!td_dummy(*dummy_td))
X printk("ED %p's dummy %p is screwy\n", ed, dummy_td);
X }
@@ -579,11 +613,11 @@
X /* set the head TD to the dummy and clear the Carry & Halted bits */
X ed->_head_td = ed->tail_td;
X
- ed->status = \
+ ed->status = cpu_to_le32(
X ed_set_maxpacket(maxpacketsize) |
X ed_set_speed(lowspeed) |
X (endp_id & 0x7ff) |
- ((isoc_tds == 0) ? OHCI_ED_F_NORM : OHCI_ED_F_ISOC);
+ ((isoc_tds == 0) ? OHCI_ED_F_NORM : OHCI_ED_F_ISOC));
X allocate_ed(ed);
X ed->next_ed = 0;
X
@@ -611,6 +645,7 @@
X struct ohci_device *dev = usb_to_ohci(usb);
X struct ohci_td *td;
X struct ohci_ed *interrupt_ed; /* endpoint descriptor for this irq */
+ int maxps = usb_maxpacket(usb, pipe);
X
X /* Get an ED and TD */
X interrupt_ed = ohci_get_free_ed(dev);
@@ -630,14 +665,16 @@
X * Set the max packet size, device speed, endpoint number, usb
X * device number (function address), and type of TD.
X */
- ohci_fill_ed(dev, interrupt_ed, usb_maxpacket(usb,pipe), usb_pipeslow(pipe),
- usb_pipe_endpdev(pipe), 0 /* normal TDs */);
+ ohci_fill_ed(dev, interrupt_ed, maxps, usb_pipeslow(pipe),
+ usb_pipe_endpdev(pipe), 0 /* normal TDs */);
X
X /* Fill in the TD */
+ if (maxps > sizeof(dev->data))
+ maxps = sizeof(dev->data);
X ohci_fill_new_td(td, td_set_dir_out(usb_pipeout(pipe)),
X TOGGLE_AUTO,
X OHCI_TD_ROUND,
- &dev->data, DATA_BUF_LEN,
+ dev->data, maxps,
X dev_id, handler);
X /*
X * TODO: be aware of how the OHCI controller deals with DMA
@@ -647,12 +684,12 @@
X /*
X * Put the TD onto our ED and make sure its ready to run
X */
- ohci_add_td_to_ed(td, interrupt_ed);
- interrupt_ed->status &= ~OHCI_ED_SKIP;
+ td = ohci_add_td_to_ed(td, td, interrupt_ed);
+ interrupt_ed->status &= cpu_to_le32(~OHCI_ED_SKIP);
X ohci_unhalt_ed(interrupt_ed);
X
- /* Linus did this. see asm/system.h; scary concept... I don't
- * know if its needed here or not but it won't hurt. */
+ /* Make sure all the stores above get done before
+ * the store which tells the OHCI about the new ed. */
X wmb();
X
X /* Assimilate the new ED into the collective */
@@ -700,7 +737,8 @@
X *
X * This function can NOT be called from an interrupt.
X */
-static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, void *cmd, void *data, int len)
+static int ohci_control_msg(struct usb_device *usb, unsigned int pipe,
+ devrequest *cmd, void *data, int len)
X {
X struct ohci_device *dev = usb_to_ohci(usb);
X struct ohci_ed *control_ed = ohci_get_free_ed(dev);
@@ -708,8 +746,16 @@
X DECLARE_WAITQUEUE(wait, current);
X unsigned long flags;
X int completion_status = -1;
+ devrequest our_cmd;
X
-#ifdef OHCI_DEBUG
+ /* byte-swap fields of cmd if necessary */
+ our_cmd = *cmd;
+ cpu_to_le16s(&our_cmd.value);
+ cpu_to_le16s(&our_cmd.index);
+ cpu_to_le16s(&our_cmd.length);
+
+#ifdef OHCI_DEBUG
+ if (MegaDebug)
X printk(KERN_DEBUG "ohci_control_msg %p (ohci_dev: %p) pipe %x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len);
X #endif
X if (!control_ed) {
@@ -743,12 +789,11 @@
X * uses a DATA0 packet.
X *
X * The setup packet contains a devrequest (usb.h) which
- * will always be 8 bytes long. FIXME: the cmd parameter
- * should be a pointer to one of these instead of a void* !!!
+ * will always be 8 bytes long.
X */
X ohci_fill_new_td(setup_td, OHCI_TD_D_SETUP, TOGGLE_DATA0,
X OHCI_TD_IOC_OFF,
- cmd, 8, /* cmd is always 8 bytes long */
+ &our_cmd, 8, /* cmd is always 8 bytes long */
X NULL, NULL);
X
X /* allocate the next TD */
@@ -761,7 +806,7 @@
X }
X
X /* link to the next TD */
- setup_td->next_td = virt_to_bus(data_td);


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part18

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


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

+ if (!(vendor = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer)))
+ vendor = "?";
+ if (!(product = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct)))
+ product = "?";
+
+ switch (us->protocol) {
+ case US_PR_CB:
+ style = "Control/Bulk";
+ break;
+
+ case US_PR_CBI:
+ style = "Control/Bulk/Interrupt";
+ break;
+
+ case US_PR_ZIP:
+ style = "Bulk only";
+ break;
+
+ }
+ SPRINTF ("Host scsi%d: usb-scsi\n", hostno);
+ SPRINTF ("Device: %s %s - GUID " GUID_FORMAT "\n", vendor, product, GUID_ARGS(us->guid) );
+ SPRINTF ("Style: %s\n", style);
+
+ /*
+ * Calculate start of next buffer, and return value.
+ */
+ *start = buffer + offset;
+
+ if ((pos - buffer) < offset)
+ return (0);
+ else if ((pos - buffer - offset) < length)
+ return (pos - buffer - offset);
+ else
+ return (length);
+}
+
+/*
+ * this defines our 'host'
+ */
+
+static Scsi_Host_Template my_host_template = {
+ NULL, /* next */
+ NULL, /* module */
+ NULL, /* proc_dir */
+ usb_scsi_proc_info,
+ NULL, /* name - points to unique */
+ us_detect,
+ us_release,
+ NULL, /* info */


+ NULL, /* ioctl */

+ us_command,
+ us_queuecommand,
+ NULL, /* eh_strategy */
+ us_abort,
+ us_device_reset,
+ us_bus_reset,
+ us_host_reset,
+ NULL, /* abort */
+ NULL, /* reset */
+ NULL, /* slave_attach */
+ NULL, /* bios_param */
+ 1, /* can_queue */
+ -1, /* this_id */
+ SG_ALL, /* sg_tablesize */
+ 1, /* cmd_per_lun */
+ 0, /* present */
+ FALSE, /* unchecked_isa_dma */
+ FALSE, /* use_clustering */
+ TRUE, /* use_new_eh_code */
+ TRUE /* emulated */
+};
+
+static int usbscsi_control_thread(void * __us)
+{
+ struct us_data *us = (struct us_data *)__us;
+ int action;
+
+ lock_kernel();
+
+ /*
+ * This thread doesn't need any user-level access,
+ * so get rid of all our resources..
+ */
+ exit_mm(current);
+ exit_files(current);
+ //exit_fs(current);
+
+ sprintf(current->comm, "usbscsi%d", us->host_no);
+
+ unlock_kernel();
+
+ up(us->notify);
+
+ for(;;) {
+ siginfo_t info;
+ int unsigned long signr;
+
+ interruptible_sleep_on(&us->waitq);
+
+ action = us->action;
+ us->action = 0;
+
+ switch (action) {
+ case US_ACT_COMMAND :
+ if (!us->pusb_dev || us->srb->target || us->srb->lun) {
+ /* bad device */
+ US_DEBUGP( "Bad device number (%d/%d) or dev %x\n", us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev);
+ us->srb->result = DID_BAD_TARGET << 16;
+ } else {
+ US_DEBUG(us_show_command(us->srb));
+ if (us->filter && us->filter->command)
+ us->srb->result = us->filter->command(us->fdata, us->srb);
+ else
+ us->srb->result = us->pop(us->srb);
+ }
+ us->srb->scsi_done(us->srb);
+ break;
+
+ case US_ACT_ABORT :
+ break;
+
+ case US_ACT_DEVICE_RESET :
+ break;
+
+ case US_ACT_BUS_RESET :
+ break;
+
+ case US_ACT_HOST_RESET :


+ break;
+
+ }
+

+ if(signal_pending(current)) {
+ /* sending SIGUSR1 makes us print out some info */
+ spin_lock_irq(&current->sigmask_lock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (signr == SIGUSR2) {
+ printk("USBSCSI debug toggle\n");
+ usbscsi_debug = !usbscsi_debug;
+ } else {


+ break;
+ }
+ }
+ }

+
+ MOD_DEC_USE_COUNT;
+
+ printk("usbscsi_control_thread exiting\n");
+
+ return 0;
+}
+
+static int scsi_probe(struct usb_device *dev)
+{
+ struct usb_interface_descriptor *interface;
+ int i;
+ char *mf; /* manufacturer */
+ char *prod; /* product */
+ char *serial; /* serial number */
+ struct us_data *ss = NULL;
+ struct usb_scsi_filter *filter = filters;
+ void *fdata = NULL;
+ unsigned int flags = 0;
+ GUID(guid);
+ struct us_data *prev;
+ Scsi_Host_Template *htmplt;
+ int protocol = 0;
+ int subclass = 0;
+
+ GUID_CLEAR(guid);
+ mf = usb_string(dev, dev->descriptor.iManufacturer);
+ prod = usb_string(dev, dev->descriptor.iProduct);
+ serial = usb_string(dev, dev->descriptor.iSerialNumber);
+
+ /* probe with filters first */
+
+ if (mf && prod) {
+ while (filter) {
+ if ((fdata = filter->probe(dev, mf, prod, serial)) != NULL) {
+ flags = filter->flags;
+ printk(KERN_INFO "USB Scsi filter %s\n", filter->name);
+ break;
+ }
+ filter = filter->next;
+ }
+ }
+
+ /* generic devices next */
+
+ if (fdata == NULL) {
+
+ /* some exceptions */
+ if (dev->descriptor.idVendor == 0x04e6 &&
+ dev->descriptor.idProduct == 0x0001) {
+ /* shuttle E-USB */
+ protocol = US_PR_ZIP;
+ subclass = US_SC_8070; /* an assumption */
+ } else if (dev->descriptor.bDeviceClass != 0 ||
+ dev->config->altsetting->interface->bInterfaceClass != 8 ||
+ dev->config->altsetting->interface->bInterfaceSubClass < US_SC_MIN ||
+ dev->config->altsetting->interface->bInterfaceSubClass > US_SC_MAX) {


+ return -1;
+ }
+

+ /* now check if we have seen it before */
+
+ if (dev->descriptor.iSerialNumber &&
+ usb_string(dev, dev->descriptor.iSerialNumber) ) {
+ make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct,
+ usb_string(dev, dev->descriptor.iSerialNumber));
+ for (ss = us_list; ss; ss = ss->next) {
+ if (GUID_EQUAL(guid, ss->guid)) {
+ US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", GUID_ARGS(guid));


+ break;
+ }
+ }
+ }

+ }
+
+ if (!ss) {
+ if ((ss = (struct us_data *)kmalloc(sizeof(*ss), GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING USB_SCSI "Out of memory\n");
+ if (filter)
+ filter->release(fdata);
+ return -1;
+ }
+ memset(ss, 0, sizeof(struct us_data));
+ }
+
+ interface = dev->config->altsetting->interface;
+ ss->filter = filter;
+ ss->fdata = fdata;
+ ss->flags = flags;
+ if (subclass) {
+ ss->subclass = subclass;
+ ss->protocol = protocol;
+ } else {
+ ss->subclass = interface->bInterfaceSubClass;
+ ss->protocol = interface->bInterfaceProtocol;
+ }
+
+ /* set the protocol op */
+
+ US_DEBUGP("Protocol ");
+ switch (ss->protocol) {
+ case US_PR_CB:
+ US_DEBUGPX("Control/Bulk\n");
+ ss->pop = pop_CBI;
+ break;
+
+ case US_PR_CBI:
+ US_DEBUGPX("Control/Bulk/Interrupt\n");
+ ss->pop = pop_CBI;
+ break;
+
+ default:
+ US_DEBUGPX("Bulk\n");
+ ss->pop = pop_Bulk;
+ break;
+ }
+
+ /*
+ * we are expecting a minimum of 2 endpoints - in and out (bulk)
+ * an optional interrupt is OK (necessary for CBI protocol)
+ * we will ignore any others
+ */
+
+ for (i = 0; i < interface->bNumEndpoints; i++) {
+ if (interface->endpoint[i].bmAttributes == 0x02) {
+ if (interface->endpoint[i].bEndpointAddress & 0x80)
+ ss->ep_in = interface->endpoint[i].bEndpointAddress & 0x0f;
+ else
+ ss->ep_out = interface->endpoint[i].bEndpointAddress & 0x0f;
+ } else if (interface->endpoint[i].bmAttributes == 0x03) {
+ ss->ep_int = interface->endpoint[i].bEndpointAddress & 0x0f;
+ }
+ }
+ US_DEBUGP("Endpoints In %d Out %d Int %d\n", ss->ep_in, ss->ep_out, ss->ep_int);
+
+ /* exit if strange looking */
+
+ if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) ||
+ !ss->ep_in || !ss->ep_out || (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
+ US_DEBUGP("Problems with device\n");
+ if (ss->host) {
+ scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt);
+ kfree(ss->htmplt->name);
+ kfree(ss->htmplt);
+ }
+ if (filter)
+ filter->release(fdata);
+ kfree(ss);
+ return -1; /* no endpoints */
+ }
+
+ if (dev->config[0].iConfiguration && usb_string(dev, dev->config[0].iConfiguration))
+ US_DEBUGP("Configuration %s\n", usb_string(dev, dev->config[0].iConfiguration));
+ if (interface->iInterface && usb_string(dev, interface->iInterface))
+ US_DEBUGP("Interface %s\n", usb_string(dev, interface->iInterface));
+
+ ss->pusb_dev = dev;
+
+ /* Now generate a scsi host definition, and register with scsi above us */
+
+ if (!ss->host) {
+
+ /* make unique id if possible */
+
+ if (dev->descriptor.iSerialNumber &&
+ usb_string(dev, dev->descriptor.iSerialNumber) ) {
+ make_guid(ss->guid, dev->descriptor.idVendor, dev->descriptor.idProduct,
+ usb_string(dev, dev->descriptor.iSerialNumber));
+ }
+
+ US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
+
+ /* set class specific stuff */
+
+ US_DEBUGP("SubClass ");
+ switch (ss->subclass) {
+ case US_SC_RBC:
+ US_DEBUGPX("Reduced Block Commands\n");
+ break;
+ case US_SC_8020:
+ US_DEBUGPX("8020\n");
+ break;
+ case US_SC_QIC:
+ US_DEBUGPX("QIC157\n");
+ break;
+ case US_SC_8070:
+ US_DEBUGPX("8070\n");
+ ss->flags |= US_FL_FIXED_COMMAND;
+ ss->fixedlength = 12;
+ break;
+ case US_SC_SCSI:
+ US_DEBUGPX("Transparent SCSI\n");
+ break;
+ case US_SC_UFI:
+ US_DEBUGPX(" UFF\n");
+ ss->flags |= US_FL_FIXED_COMMAND;
+ ss->fixedlength = 12;
+ break;
+
+ default:
+ break;
+ }
+
+ /* create unique host template */
+
+ if ((htmplt = (Scsi_Host_Template *)kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {
+ printk(KERN_WARNING USB_SCSI "Out of memory\n");
+ if (filter)
+ filter->release(fdata);
+ kfree(ss);
+ return -1;
+ }
+ memcpy(htmplt, &my_host_template, sizeof(my_host_template));
+ ss->host_number = my_host_number++;
+
+
+ (struct us_data *)htmplt->proc_dir = ss;
+ if (ss->protocol == US_PR_CBI)
+ init_waitqueue_head(&ss->ip_waitq);
+
+ /* start up our thread */
+
+ {
+ DECLARE_MUTEX_LOCKED(sem);
+
+ init_waitqueue_head(&ss->waitq);
+
+ ss->notify = &sem;
+ ss->pid = kernel_thread(usbscsi_control_thread, ss,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ if (ss->pid < 0) {
+ printk(KERN_WARNING USB_SCSI "Unable to start control thread\n");
+ kfree(htmplt);
+ if (filter)
+ filter->release(fdata);
+ kfree(ss);


+ return -1;
+ }
+

+ /* wait for it to start */
+
+ down(&sem);
+ }
+
+ /* now register - our detect function will be called */
+
+ scsi_register_module(MODULE_SCSI_HA, htmplt);
+
+ /* put us in the list */
+
+ prev = (struct us_data *)&us_list;
+ while (prev->next)
+ prev = prev->next;
+ prev->next = ss;
+
+ }
+
+
+ printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum);
+
+ dev->private = ss;
+ return 0;
+}
+
+static void scsi_disconnect(struct usb_device *dev)
+{
+ struct us_data *ss = dev->private;
+
+ if (!ss)
+ return;
+ if (ss->filter)
+ ss->filter->release(ss->fdata);
+ ss->pusb_dev = NULL;
+ dev->private = NULL; /* just in case */
+ MOD_DEC_USE_COUNT;
+}
+
+int usb_scsi_init(void)
+{
+
+ MOD_INC_USE_COUNT;
+#ifdef CONFIG_USB_HP4100
+ hp4100_init();
+#endif
+#ifdef CONFIG_USB_ZIP
+ usb_zip_init();
+#endif
+ usb_register(&scsi_driver);
+ printk(KERN_INFO "USB SCSI support registered.\n");


+ return 0;
+}
+
+

+int usb_scsi_register(struct usb_scsi_filter *filter)
+{
+ struct usb_scsi_filter *prev = (struct usb_scsi_filter *)&filters;
+
+ while (prev->next)
+ prev = prev->next;
+ prev->next = filter;


+ return 0;
+}
+

+void usb_scsi_deregister(struct usb_scsi_filter *filter)
+{
+ struct usb_scsi_filter *prev = (struct usb_scsi_filter *)&filters;
+
+ while (prev->next && prev->next != filter)
+ prev = prev->next;
+ if (prev->next)
+ prev->next = filter->next;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+
+ return usb_scsi_init();


+}
+
+void cleanup_module(void)
+{

+ unsigned int offset;
+
+ usb_deregister(&scsi_driver);
+}
+#endif
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/usb_scsi.h linux/drivers/usb/usb_scsi.h
--- v2.3.5/linux/drivers/usb/usb_scsi.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/usb_scsi.h Mon Jun 7 20:04:01 1999
@@ -0,0 +1,145 @@
+/* Driver for USB scsi - include file
+ *
+ * (C) Michael Gee (mic...@linuxspecific.com) 1999
+ *
+ * This driver is scitzoid - it make a USB scanner appear as both a SCSI device
+ * and a character device. The latter is only available if the device has an
+ * interrupt endpoint, and is used specifically to receive interrupt events.
+ *
+ * In order to support various 'strange' scanners, this module supports plug in
+ * device specific filter modules, which can do their own thing when required.
+ *
+ */
+
+#define USB_SCSI "usbscsi: "
+
+extern int usbscsi_debug;
+
+#ifdef CONFIG_USB_SCSI_DEBUG
+void us_show_command(Scsi_Cmnd *srb);
+#define US_DEBUGP(x...) { if(usbscsi_debug) printk( KERN_DEBUG USB_SCSI ## x ); }
+#define US_DEBUGPX(x...) { if(usbscsi_debug) printk( ## x ); }
+#define US_DEBUG(x) { if(usbscsi_debug) x; }
+#else
+#define US_DEBUGP(x...)
+#define US_DEBUGPX(x...)
+#define US_DEBUG(x)
+#endif
+
+/* bit set if input */
+extern unsigned char us_direction[256/8];
+#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
+
+/* Sub Classes */
+
+#define US_SC_RBC 1 /* Typically, flash devices */
+#define US_SC_8020 2 /* CD-ROM */
+#define US_SC_QIC 3 /* QIC-157 Tapes */
+#define US_SC_UFI 4 /* Floppy */
+#define US_SC_8070 5 /* Removable media */
+#define US_SC_SCSI 6 /* Transparent */
+#define US_SC_MIN US_SC_RBC
+#define US_SC_MAX US_SC_SCSI
+
+/* Protocols */
+
+#define US_PR_CB 1 /* Control/Bulk w/o interrupt */
+#define US_PR_CBI 0 /* Control/Bulk/Interrupt */
+#define US_PR_ZIP 0x50 /* bulk only */
+/* #define US_PR_BULK ?? */
+
+/*
+ * Bulk only data structures (Zip 100, for example)
+ */
+
+struct bulk_cb_wrap {
+ __u32 Signature; /* contains 'USBC' */
+ __u32 Tag; /* unique per command id */
+ __u32 DataTransferLength; /* size of data */
+ __u8 Flags; /* direction in bit 0 */
+ __u8 Lun; /* LUN normally 0 */
+ __u8 Length; /* of of the CDB */
+ __u8 CDB[16]; /* max command */
+};
+
+#define US_BULK_CB_WRAP_LEN 31
+#define US_BULK_CB_SIGN 0x43425355
+#define US_BULK_FLAG_IN 1
+#define US_BULK_FLAG_OUT 0
+
+struct bulk_cs_wrap {
+ __u32 Signature; /* should = 'USBS' */
+ __u32 Tag; /* same as original command */
+ __u32 Residue; /* amount not transferred */
+ __u8 Status; /* see below */
+ __u8 Filler[18];
+};
+
+#define US_BULK_CS_WRAP_LEN 31
+#define US_BULK_CS_SIGN 0x53425355
+#define US_BULK_STAT_OK 0
+#define US_BULK_STAT_FAIL 1
+#define US_BULK_STAT_PHASE 2
+
+#define US_BULK_RESET 0xff
+#define US_BULK_RESET_SOFT 1
+#define US_BULK_RESET_HARD 0
+
+/*
+ * CBI style
+ */
+
+#define US_CBI_ADSC 0
+
+/*
+ * Filter device definitions
+ */
+struct usb_scsi_filter {
+
+ struct usb_scsi_filter * next; /* usb_scsi driver only */
+ char *name; /* not really required */
+
+ unsigned int flags; /* Filter flags */
+ void * (* probe) (struct usb_device *, char *, char *, char *); /* probe device */
+ void (* release)(void *); /* device gone */
+ int (* command)(void *, Scsi_Cmnd *); /* all commands */
+};
+
+#define GUID(x) __u32 x[3]
+#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2])
+#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0;
+#define GUID_NONE(x) (!x[0] && !x[1] && !x[2])
+#define GUID_FORMAT "%08x%08x%08x"
+#define GUID_ARGS(x) x[0], x[1], x[2]
+
+static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial)
+{
+ pg[0] = (vendor << 16) | product;
+ pg[1] = pg[2] = 0;
+ while (*serial) {
+ pg[1] <<= 4;
+ pg[1] |= pg[2] >> 28;
+ pg[2] <<= 4;
+ if (*serial >= 'a')
+ *serial -= 'a' - 'A';
+ pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0'
+ : *serial - 'A' + 10;
+ serial++;
+ }
+}
+
+/* Flag definitions */
+#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */
+#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */
+
+/*
+ * Called by filters to register/unregister the mini driver
+ *
+ * WARNING - the supplied probe function may be called before exiting this fn
+ */
+int usb_scsi_register(struct usb_scsi_filter *);
+void usb_scsi_deregister(struct usb_scsi_filter *);
+
+#ifdef CONFIG_USB_HP4100
+int hp4100_init(void);
+#endif
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/usb_scsi_debug.c linux/drivers/usb/usb_scsi_debug.c
--- v2.3.5/linux/drivers/usb/usb_scsi_debug.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/usb_scsi_debug.c Mon Jun 7 20:04:01 1999
@@ -0,0 +1,104 @@
+
+/* Driver for USB scsi like devices
+ *
+ * (C) Michael Gee (mic...@linuxspecific.com) 1999


+ *
+ */
+

+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/spinlock.h>
+
+#include <linux/blk.h>
+#include "../scsi/scsi.h"
+#include "../scsi/hosts.h"
+#include "../scsi/sd.h"
+
+#include "usb.h"
+#include "usb_scsi.h"
+
+void us_show_command(Scsi_Cmnd *srb)
+{
+ char *what;
+
+ switch (srb->cmnd[0]) {
+ case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
+ case REZERO_UNIT: what = "REZERO_UNIT"; break;
+ case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
+ case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
+ case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
+ case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
+ case READ_6: what = "READ_6"; break;
+ case WRITE_6: what = "WRITE_6"; break;
+ case SEEK_6: what = "SEEK_6"; break;
+ case READ_REVERSE: what = "READ_REVERSE"; break;
+ case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
+ case SPACE: what = "SPACE"; break;
+ case INQUIRY: what = "INQUIRY"; break;
+ case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
+ case MODE_SELECT: what = "MODE_SELECT"; break;
+ case RESERVE: what = "RESERVE"; break;
+ case RELEASE: what = "RELEASE"; break;
+ case COPY: what = "COPY"; break;
+ case ERASE: what = "ERASE"; break;
+ case MODE_SENSE: what = "MODE_SENSE"; break;
+ case START_STOP: what = "START_STOP"; break;
+ case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
+ case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
+ case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
+ case SET_WINDOW: what = "SET_WINDOW"; break;
+ case READ_CAPACITY: what = "READ_CAPACITY"; break;
+ case READ_10: what = "READ_10"; break;
+ case WRITE_10: what = "WRITE_10"; break;
+ case SEEK_10: what = "SEEK_10"; break;
+ case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
+ case VERIFY: what = "VERIFY"; break;
+ case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
+ case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
+ case SEARCH_LOW: what = "SEARCH_LOW"; break;
+ case SET_LIMITS: what = "SET_LIMITS"; break;
+ case READ_POSITION: what = "READ_POSITION"; break;
+ case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
+ case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
+ case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
+ case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
+ case COMPARE: what = "COMPARE"; break;
+ case COPY_VERIFY: what = "COPY_VERIFY"; break;
+ case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
+ case READ_BUFFER: what = "READ_BUFFER"; break;
+ case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
+ case READ_LONG: what = "READ_LONG"; break;
+ case WRITE_LONG: what = "WRITE_LONG"; break;
+ case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
+ case WRITE_SAME: what = "WRITE_SAME"; break;
+ case READ_TOC: what = "READ_TOC"; break;
+ case LOG_SELECT: what = "LOG_SELECT"; break;
+ case LOG_SENSE: what = "LOG_SENSE"; break;
+ case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
+ case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
+ case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
+ case READ_12: what = "READ_12"; break;
+ case WRITE_12: what = "WRITE_12"; break;
+ case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
+ case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
+ case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
+ case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
+ case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
+ case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
+ case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
+ default: what = "??"; break;
+ }
+ printk(KERN_DEBUG USB_SCSI "Command %s (%d bytes)\n", what, srb->cmd_len);
+ printk(KERN_DEBUG USB_SCSI " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
+ srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
+}
diff -u --recursive --new-file v2.3.5/linux/drivers/usb/usb_scsi_dt.c linux/drivers/usb/usb_scsi_dt.c
--- v2.3.5/linux/drivers/usb/usb_scsi_dt.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/usb_scsi_dt.c Mon Jun 7 20:04:01 1999
@@ -0,0 +1,4 @@
+0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
+0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff -u --recursive --new-file v2.3.5/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.5/linux/drivers/video/atyfb.c Thu Apr 22 19:30:08 1999
+++ linux/drivers/video/atyfb.c Wed Jun 9 14:44:25 1999
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.106 1999/04/16 11:20:49 geert Exp $
+/* $Id: atyfb.c,v 1.107 1999/06/08 19:59:03 geert Exp $
X * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
X *
X * Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -200,6 +200,7 @@
X struct atyfb_par default_par;
X struct atyfb_par current_par;
X u32 total_vram;
+ u32 ref_clk_per;
X u32 pll_per;
X u32 mclk_per;
X u16 chip_type;
@@ -326,9 +327,7 @@
X static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
X static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
X static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
-#if defined(__sparc__) || defined(DEBUG)
X static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
-#endif
X static void aty_set_crtc(const struct fb_info_aty *info,
X const struct crtc *crtc);
X static int aty_var_to_crtc(const struct fb_info_aty *info,
@@ -341,7 +340,8 @@
X const struct pll_gx *pll);
X static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll);
X static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
-static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per);
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per,
+ const struct fb_info_aty *info);
X static void aty_set_pll_ct(const struct fb_info_aty *info,
X const struct pll_ct *pll);
X static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
@@ -349,7 +349,8 @@
X u8 bpp, struct pll_ct *pll);
X static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
X u8 bpp, struct pll_ct *pll);
-static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per);
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per,
+ const struct fb_info_aty *info);
X static void atyfb_set_par(const struct atyfb_par *par,
X struct fb_info_aty *info);
X static int atyfb_decode_var(const struct fb_var_screeninfo *var,
@@ -405,8 +406,6 @@
X static int default_pll __initdata = 0;
X static int default_mclk __initdata = 0;
X
-static const u32 ref_clk_per = 1000000000000ULL/14318180;
-
X #if defined(CONFIG_PPC)
X static int default_vmode __initdata = VMODE_NVRAM;
X static int default_cmode __initdata = CMODE_NVRAM;
@@ -689,7 +688,6 @@
X aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
X }
X
-#if defined(__sparc__) || defined(DEBUG)
X static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
X {
X u8 res;
@@ -702,7 +700,6 @@
X eieio();
X return res;
X }
-#endif
X
X #if defined(CONFIG_PPC)
X
@@ -1455,7 +1452,8 @@
X
X /* FIXME: ATI18818?? */
X
-static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per)
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per,
+ const struct fb_info_aty *info)
X {
X u8 df, vco_div_count, ref_div_count;
X
@@ -1463,7 +1461,7 @@
X vco_div_count = pll->m & 0x3f;
X ref_div_count = pll->n;
X
- *vclk_per = ((ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
+ *vclk_per = ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);


X
X return 0;
X }

@@ -1579,10 +1577,10 @@
X
X pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
X
- pll_ref_div = info->pll_per*2*255/ref_clk_per;
+ pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
X
X /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
- q = ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */
+ q = info->ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */
X if (q < 16*8 || q > 255*8)
X FAIL("mclk out of range");
X else if (q < 32*8)
@@ -1596,7 +1594,7 @@
X mclk_fb_div = q*mclk_post_div/8;
X
X /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
- q = ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */
+ q = info->ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */
X if (q < 16*8 || q > 255*8)
X FAIL("vclk out of range");
X else if (q < 32*8)
@@ -1677,7 +1675,8 @@


X return 0;
X }
X

-static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per)
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per,
+ const struct fb_info_aty *info)
X {
X u8 pll_ref_div = pll->pll_ref_div;
X u8 vclk_fb_div = pll->vclk_fb_div;
@@ -1691,7 +1690,7 @@
X (vclk_post_div & 3)];
X if (vpostdiv == 0)
X return -EINVAL;
- *vclk_per = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
+ *vclk_per = pll_ref_div*vpostdiv*info->ref_clk_per/vclk_fb_div/2;


X return 0;
X }
X

@@ -1845,9 +1844,9 @@
X if ((err = aty_crtc_to_var(&par->crtc, var)))
X return err;
X if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
- err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock);
+ err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock, info);
X else
- err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock);
+ err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock, info);
X if (err)
X return err;
X
@@ -2432,11 +2431,12 @@
X int j, k;
X struct fb_var_screeninfo var;
X struct display *disp;
- const char *chipname = NULL, *ramname = NULL;
+ const char *chipname = NULL, *ramname = NULL, *xtal;
X int pll, mclk, gtb_memsize;
X #if defined(CONFIG_PPC)
X int sense;
X #endif
+ u8 pll_ref_div;
X
X info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
X chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
@@ -2524,6 +2524,25 @@
X }
X }
X
+ info->ref_clk_per = 1000000000000ULL/14318180;
+ xtal = "14.31818";
+ if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
+ Gx == ET_CHIP_ID ||
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) &&
+ (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
+ int diff1, diff2;
+ diff1 = 510*14/pll_ref_div-pll;
+ diff2 = 510*29/pll_ref_div-pll;
+ if (diff1 < 0)
+ diff1 = -diff1;
+ if (diff2 < 0)
+ diff2 = -diff2;
+ if (diff2 < diff1) {
+ info->ref_clk_per = 1000000000000ULL/29498928;
+ xtal = "29.498928";
+ }
+ }
+
X i = aty_ld_le32(MEM_CNTL, info);
X gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
X Gx == ET_CHIP_ID ||
@@ -2602,9 +2621,9 @@
X if (default_mclk)
X mclk = default_mclk;
X
- printk("%d%c %s, %d MHz PLL, %d Mhz MCLK\n",
+ printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
X info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
- info->total_vram == 0x80000 ? 'K' : 'M', ramname, pll, mclk);
+ info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
X
X if (mclk < 44)
X info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
diff -u --recursive --new-file v2.3.5/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
--- v2.3.5/linux/drivers/video/igafb.c Sun Mar 7 10:39:03 1999
+++ linux/drivers/video/igafb.c Wed Jun 9 14:44:26 1999
@@ -630,6 +630,7 @@
X struct fb_info_iga *info;
X unsigned long addr;
X extern int con_is_present(void);
+ int iga2000 = 0;
X
X /* Do not attach when we have a serial console. */
X if (!con_is_present())
@@ -637,8 +638,13 @@
X
X pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
X PCI_DEVICE_ID_INTERG_1682, 0);
- if(pdev == NULL)
- return;
+ if (pdev == NULL) {
+ pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
+ 0x2000, 0);
+ if(pdev == NULL)
+ return;
+ iga2000 = 1;
+ }
X
X info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
X if (!info) {
@@ -648,8 +654,10 @@
X memset(info, 0, sizeof(struct fb_info_iga));
X
X info->frame_buffer = pdev->base_address[0];
- if (!info->frame_buffer)
+ if (!info->frame_buffer) {
+ kfree(info);
X return;
+ }
X
X pcibios_read_config_dword(0, pdev->devfn,
X PCI_BASE_ADDRESS_0,
@@ -659,12 +667,23 @@
X info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
X
X #ifdef __sparc__
-
+
X info->io_base_phys = info->frame_buffer_phys;
-
- /* Obtain virtual address and correct physical by PCIC shift */
- info->io_base = pcic_alloc_io(&info->io_base_phys);
+
+ /*
+ * The right test would be to look if there is a base I/O address.
+ * But it appears that IGA 1682 reuses _memory_ address as a base
+ * for I/O accesses.
+ */
+ if (iga2000) {
+ info->io_base = (int) sparc_alloc_io(info->frame_buffer_phys |
+ 0x00800000, NULL, 0x1000, "iga", 0, 0);
+ } else {
+ /* Obtain virtual address and correct physical by PCIC shift */
+ info->io_base = pcic_alloc_io(&info->io_base_phys);
+ }
X if (!info->io_base) {
+ kfree(info);
X return;
X }
X
@@ -679,6 +698,7 @@
X info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
X if (!info->mmap_map) {
X printk("igafb_init: can't alloc mmap_map\n");
+ /* XXX Here we left I/O allocated */
X kfree(info);
X return;


X }
@@ -730,11 +750,11 @@
X }

X
X #endif
- if (!iga_init(info)) {
- if (info->mmap_map)
- kfree(info->mmap_map);
- kfree(info);
- }
+ if (!iga_init(info)) {
+ if (info->mmap_map)
+ kfree(info->mmap_map);
+ kfree(info);
+ }
X
X #ifdef __sparc__
X /*
diff -u --recursive --new-file v2.3.5/linux/fs/Config.in linux/fs/Config.in
--- v2.3.5/linux/fs/Config.in Mon May 31 22:28:06 1999
+++ linux/fs/Config.in Wed Jun 9 18:42:08 1999
@@ -73,9 +73,9 @@
X fi
X if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X tristate 'NFS server support' CONFIG_NFSD
- fi
- if [ "$CONFIG_NFSD" != "n" ]; then
- bool ' Emulate SUN NFS server' CONFIG_NFSD_SUN
+ if [ "$CONFIG_NFSD" != "n" ]; then
+ bool ' Emulate SUN NFS server' CONFIG_NFSD_SUN
+ fi
X fi
X if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
X define_bool CONFIG_SUNRPC y
diff -u --recursive --new-file v2.3.5/linux/fs/adfs/super.c linux/fs/adfs/super.c
--- v2.3.5/linux/fs/adfs/super.c Fri Mar 26 13:57:41 1999
+++ linux/fs/adfs/super.c Tue Jun 8 10:47:58 1999
@@ -300,7 +300,7 @@
X */
X sb->s_op = &adfs_sops;
X sb->u.adfs_sb.s_root = adfs_inode_generate(dr->root, 0);
- sb->s_root = d_alloc_root(iget(sb, sb->u.adfs_sb.s_root), NULL);
+ sb->s_root = d_alloc_root(iget(sb, sb->u.adfs_sb.s_root));
X
X if (!sb->s_root) {
X for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
@@ -312,8 +312,7 @@
X return sb;
X
X error_free_bh:
- if (bh)
- brelse(bh);
+ brelse(bh);
X error_unlock:
X unlock_super(sb);
X error_dec_use:
diff -u --recursive --new-file v2.3.5/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.3.5/linux/fs/affs/super.c Sun Mar 7 15:25:23 1999
+++ linux/fs/affs/super.c Tue Jun 8 10:47:58 1999
@@ -543,7 +543,7 @@
X root_inode = iget(s,root_block);
X if (!root_inode)
X goto out_no_root;
- s->s_root = d_alloc_root(root_inode, NULL);
+ s->s_root = d_alloc_root(root_inode);
X if (!s->s_root)
X goto out_no_root;
X s->s_root->d_op = &affs_dentry_operations;
diff -u --recursive --new-file v2.3.5/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.3.5/linux/fs/autofs/inode.c Mon Jan 11 15:03:30 1999
+++ linux/fs/autofs/inode.c Tue Jun 8 10:47:58 1999
@@ -176,7 +176,7 @@
X * Get the root inode and dentry, but defer checking for errors.
X */
X root_inode = iget(s, AUTOFS_ROOT_INO);
- root = d_alloc_root(root_inode, NULL);
+ root = d_alloc_root(root_inode);
X pipe = NULL;
X
X /*
diff -u --recursive --new-file v2.3.5/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.3.5/linux/fs/binfmt_aout.c Wed Jun 2 14:44:39 1999
+++ linux/fs/binfmt_aout.c Tue Jun 8 23:01:35 1999
@@ -49,9 +49,7 @@


X end = PAGE_ALIGN(end);
X if (end <= start)
X return;
- do_mmap(NULL, start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, 0);
+ do_brk(start, end - start);

X }
X
X /*
@@ -372,14 +370,10 @@
X #ifdef __sparc__


X if (N_MAGIC(ex) == NMAGIC) {
X /* Fuck me plenty... */
- error = do_mmap(NULL, N_TXTADDR(ex), ex.a_text,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
X read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
X ex.a_text, 0);
- error = do_mmap(NULL, N_DATADDR(ex), ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
X read_exec(bprm->dentry, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
X ex.a_data, 0);
X goto beyond_if;

@@ -388,16 +382,12 @@


X
X if (N_MAGIC(ex) == OMAGIC) {

X #if defined(__alpha__) || defined(__sparc__)


- do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
- ex.a_text+ex.a_data + PAGE_SIZE - 1,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(N_TXTADDR(ex) & PAGE_MASK,
+ ex.a_text+ex.a_data + PAGE_SIZE - 1);
X read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
X ex.a_text+ex.a_data, 0);

X #else


- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(0, ex.a_text+ex.a_data);

X read_exec(bprm->dentry, 32, (char *) 0, ex.a_text+ex.a_data, 0);
X #endif
X flush_icache_range((unsigned long) 0,
@@ -421,9 +411,7 @@
X
X if (!file->f_op || !file->f_op->mmap || ((fd_offset & ~PAGE_MASK) != 0)) {


X sys_close(fd);
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(0, ex.a_text+ex.a_data);
X read_exec(bprm->dentry, fd_offset,
X (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);

X flush_icache_range((unsigned long) N_TXTADDR(ex),
@@ -574,9 +562,7 @@


X len = PAGE_ALIGN(ex.a_text + ex.a_data);
X bss = ex.a_text + ex.a_data + ex.a_bss;
X if (bss > len) {
- error = do_mmap(NULL, start_addr + len, bss - len,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_FIXED, 0);
+ error = do_brk(start_addr + len, bss - len);
X retval = error;
X if (error != start_addr + len)
X goto out_putf;

diff -u --recursive --new-file v2.3.5/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.3.5/linux/fs/binfmt_elf.c Wed Jun 2 14:44:39 1999
+++ linux/fs/binfmt_elf.c Thu Jun 3 23:15:29 1999
@@ -77,9 +77,7 @@
X end = ELF_PAGEALIGN(end);


X if (end <= start)
X return;
- do_mmap(NULL, start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, 0);
+ do_brk(start, end - start);
X }
X
X

@@ -328,9 +326,7 @@


X
X /* Map the last of the bss segment */

X if (last_bss > elf_bss)
- do_mmap(NULL, elf_bss, last_bss - elf_bss,


- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);

+ do_brk(elf_bss, last_bss - elf_bss);
X
X *interp_load_addr = load_addr;
X error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;
@@ -370,17 +366,15 @@


X goto out;
X }
X

- do_mmap(NULL, 0, text_data,
- PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(0, text_data);
X retval = read_exec(interpreter_dentry, offset, addr, text_data, 0);
X if (retval < 0)
X goto out;
X flush_icache_range((unsigned long)addr,
X (unsigned long)addr + text_data);
X
- do_mmap(NULL, ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1),
- interp_ex->a_bss,
- PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1),
+ interp_ex->a_bss);
X elf_entry = interp_ex->a_entry;
X
X out:
@@ -885,9 +879,7 @@
X ELF_EXEC_PAGESIZE - 1);


X bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;

X if (bss > len)
- do_mmap(NULL, len, bss - len,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ do_brk(len, bss - len);
X error = 0;
X
X out_free_ph:
diff -u --recursive --new-file v2.3.5/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.5/linux/fs/buffer.c Sat May 15 23:46:04 1999
+++ linux/fs/buffer.c Tue Jun 8 10:47:58 1999
@@ -90,7 +90,7 @@
X /* The dummy values in this structure are left in there for compatibility
X * with old programs that play with the /proc entries.
X */
-union bdflush_param{
+union bdflush_param {
X struct {
X int nfract; /* Percentage of buffer cache dirty to
X activate bdflush */
diff -u --recursive --new-file v2.3.5/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.3.5/linux/fs/coda/inode.c Wed Mar 10 17:03:52 1999
+++ linux/fs/coda/inode.c Tue Jun 8 10:47:58 1999
@@ -115,7 +115,7 @@
X printk("coda_read_super: rootinode is %ld dev %d\n",
X root->i_ino, root->i_dev);
X sbi->sbi_root = root;
- sb->s_root = d_alloc_root(root, NULL);
+ sb->s_root = d_alloc_root(root);
X unlock_super(sb);
X EXIT;
X return sb;
@@ -145,7 +145,7 @@
X sb->s_dev = 0;
X coda_cache_clear_all(sb);
X sb_info = coda_sbp(sb);
- sb_info->sbi_vcomm->vc_inuse = 0;
+/* sb_info->sbi_vcomm->vc_inuse = 0; You can not do this: psdev_release would see usagecount == 0 and would refuse to decrease MOD_USE_COUNT --pavel */
X coda_super_info.sbi_sb = NULL;
X printk("Coda: Bye bye.\n");
X memset(sb_info, 0, sizeof(* sb_info));
diff -u --recursive --new-file v2.3.5/linux/fs/dcache.c linux/fs/dcache.c
--- v2.3.5/linux/fs/dcache.c Sun Apr 25 23:17:56 1999
+++ linux/fs/dcache.c Tue Jun 8 10:47:58 1999
@@ -546,7 +546,7 @@
X entry->d_inode = inode;
X }
X
-struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
+struct dentry * d_alloc_root(struct inode * root_inode)
X {
X struct dentry *res = NULL;
X
diff -u --recursive --new-file v2.3.5/linux/fs/devpts/inode.c linux/fs/devpts/inode.c
--- v2.3.5/linux/fs/devpts/inode.c Wed Jun 2 14:44:39 1999
+++ linux/fs/devpts/inode.c Tue Jun 8 10:47:58 1999
@@ -163,7 +163,7 @@
X * Get the root inode and dentry, but defer checking for errors.
X */
X root_inode = iget(s, 1); /* inode 1 == root directory */
- root = d_alloc_root(root_inode, NULL);
+ root = d_alloc_root(root_inode);
X
X /*
X * Check whether somebody else completed the super block.
diff -u --recursive --new-file v2.3.5/linux/fs/efs/super.c linux/fs/efs/super.c
--- v2.3.5/linux/fs/efs/super.c Mon May 31 22:28:06 1999
+++ linux/fs/efs/super.c Tue Jun 8 10:47:58 1999
@@ -204,7 +204,7 @@
X }
X s->s_op = &efs_superblock_operations;
X s->s_dev = dev;
- s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE), NULL);
+ s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE));
X unlock_super(s);
X
X if (!(s->s_root)) {
diff -u --recursive --new-file v2.3.5/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.3.5/linux/fs/ext2/super.c Mon Apr 12 10:03:45 1999
+++ linux/fs/ext2/super.c Tue Jun 8 10:47:58 1999
@@ -629,7 +629,7 @@
X */
X sb->s_dev = dev;
X sb->s_op = &ext2_sops;
- sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO), NULL);
+ sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
X if (!sb->s_root) {
X sb->s_dev = 0;
X for (i = 0; i < db_count; i++)
diff -u --recursive --new-file v2.3.5/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
--- v2.3.5/linux/fs/ext2/symlink.c Sat Sep 19 13:38:18 1998
+++ linux/fs/ext2/symlink.c Wed Jun 9 20:46:53 1999
@@ -102,7 +102,6 @@
X i++;
X if (copy_to_user(buffer, link, i))
X i = -EFAULT;
- UPDATE_ATIME(inode);
X if (bh)
X brelse (bh);
X return i;
diff -u --recursive --new-file v2.3.5/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.3.5/linux/fs/fat/inode.c Sat May 15 23:46:04 1999
+++ linux/fs/fat/inode.c Tue Jun 8 10:47:58 1999
@@ -650,7 +650,7 @@
X root_inode->i_ino = MSDOS_ROOT_INO;
X fat_read_root(root_inode);
X insert_inode_hash(root_inode);
- sb->s_root = d_alloc_root(root_inode, NULL);
+ sb->s_root = d_alloc_root(root_inode);
X if (!sb->s_root)
X goto out_no_root;
X if(i>=0) {
diff -u --recursive --new-file v2.3.5/linux/fs/fcntl.c linux/fs/fcntl.c
--- v2.3.5/linux/fs/fcntl.c Fri Nov 13 10:07:26 1998
+++ linux/fs/fcntl.c Mon Jun 7 12:10:22 1999
@@ -183,26 +183,15 @@
X return err;
X }
X
-static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
+static void send_sigio_to_task(struct task_struct *p,
+ struct fown_struct *fown, struct fasync_struct *fa)
X {
- struct task_struct * p;
- int pid = fown->pid;
- uid_t uid = fown->uid;
- uid_t euid = fown->euid;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- int match = p->pid;
- if (pid < 0)
- match = -p->pgrp;
- if (pid != match)
- continue;
- if ((euid != 0) &&
- (euid ^ p->suid) && (euid ^ p->uid) &&
- (uid ^ p->suid) && (uid ^ p->uid))
- continue;
- switch (fown->signum) {
- siginfo_t si;
+ if ((fown->euid != 0) &&
+ (fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
+ (fown->uid ^ p->suid) && (fown->uid ^ p->uid))
+ return;
+ switch (fown->signum) {
+ siginfo_t si;
X default:
X /* Queue a rt signal with the appropriate fd as its
X value. We use SI_SIGIO as the source, not
@@ -213,16 +202,36 @@
X si.si_signo = fown->signum;
X si.si_errno = 0;
X si.si_code = SI_SIGIO;
- si.si_pid = pid;
- si.si_uid = uid;
+ si.si_pid = fown->pid;
+ si.si_uid = fown->uid;
X si.si_fd = fa->fa_fd;
X if (!send_sig_info(fown->signum, &si, p))
X break;
X /* fall-through: fall back on the old plain SIGIO signal */
X case 0:
X send_sig(SIGIO, p, 1);
- }
X }
+}
+
+static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
+{
+ struct task_struct * p;
+ int pid = fown->pid;
+
+ read_lock(&tasklist_lock);
+ if ( (pid > 0) && (p = find_task_by_pid(pid)) ) {
+ send_sigio_to_task(p, fown, fa);
+ goto out;
+ }
+ for_each_task(p) {
+ int match = p->pid;
+ if (pid < 0)
+ match = -p->pgrp;
+ if (pid != match)
+ continue;
+ send_sigio_to_task(p, fown, fa);
+ }
+out:
X read_unlock(&tasklist_lock);
X }
X
diff -u --recursive --new-file v2.3.5/linux/fs/hfs/bnode.c linux/fs/hfs/bnode.c
--- v2.3.5/linux/fs/hfs/bnode.c Mon May 17 09:55:22 1999
+++ linux/fs/hfs/bnode.c Fri Jun 4 13:30:25 1999
@@ -123,6 +123,8 @@
X bnode->tree = tree;
X bnode->node = node;
X bnode->sticky = sticky;
+ hfs_init_waitqueue(&bnode->rqueue);
+ hfs_init_waitqueue(&bnode->wqueue);
X
X if (sticky == HFS_NOT_STICKY) {
X /* Insert it in the cache if appropriate */
diff -u --recursive --new-file v2.3.5/linux/fs/hfs/btree.c linux/fs/hfs/btree.c
--- v2.3.5/linux/fs/hfs/btree.c Fri May 14 18:55:24 1999
+++ linux/fs/hfs/btree.c Fri Jun 4 13:30:25 1999
@@ -173,7 +173,7 @@
X bt->sys_mdb = mdb->sys_mdb;
X bt->reserved = 0;
X bt->lock = 0;
- init_waitqueue_head(&bt->wait);
+ hfs_init_waitqueue(&bt->wait);
X bt->dirt = 0;
X memset(bt->cache, 0, sizeof(bt->cache));
X
diff -u --recursive --new-file v2.3.5/linux/fs/hfs/catalog.c linux/fs/hfs/catalog.c
--- v2.3.5/linux/fs/hfs/catalog.c Mon May 17 09:55:22 1999
+++ linux/fs/hfs/catalog.c Fri Jun 4 13:30:25 1999
@@ -302,6 +302,8 @@
X entry->modify_date = hfs_get_nl(cat->u.dir.MdDat);
X entry->backup_date = hfs_get_nl(cat->u.dir.BkDat);
X dir->dirs = dir->files = 0;
+ hfs_init_waitqueue(&dir->read_wait);
+ hfs_init_waitqueue(&dir->write_wait);
X } else if (cat->cdrType == HFS_CDR_FIL) {
X struct hfs_file *fil = &entry->u.file;
X
diff -u --recursive --new-file v2.3.5/linux/fs/hfs/mdb.c linux/fs/hfs/mdb.c
--- v2.3.5/linux/fs/hfs/mdb.c Wed Dec 23 14:10:36 1998
+++ linux/fs/hfs/mdb.c Fri Jun 4 13:30:25 1999
@@ -99,7 +99,9 @@
X memset(mdb, 0, sizeof(*mdb));
X mdb->magic = HFS_MDB_MAGIC;
X mdb->sys_mdb = sys_mdb;
- INIT_LIST_HEAD(&mdb->entry_dirty);
+ INIT_LIST_HEAD(&mdb->entry_dirty);
+ hfs_init_waitqueue(&mdb->rename_wait);
+ hfs_init_waitqueue(&mdb->bitmap_wait);
X
X /* See if this is an HFS filesystem */
X buf = hfs_buffer_get(sys_mdb, part_start + HFS_MDB_BLK, 1);
diff -u --recursive --new-file v2.3.5/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.3.5/linux/fs/hfs/super.c Fri May 14 18:55:24 1999
+++ linux/fs/hfs/super.c Tue Jun 8 10:47:58 1999
@@ -466,7 +466,7 @@
X if (!root_inode)
X goto bail_no_root;
X
- s->s_root = d_alloc_root(root_inode, NULL);
+ s->s_root = d_alloc_root(root_inode);
X if (!s->s_root)
X goto bail_no_root;
X
diff -u --recursive --new-file v2.3.5/linux/fs/hpfs/alloc.c linux/fs/hpfs/alloc.c
--- v2.3.5/linux/fs/hpfs/alloc.c Mon May 17 09:55:22 1999
+++ linux/fs/hpfs/alloc.c Fri Jun 4 01:06:29 1999
@@ -164,8 +164,11 @@
X if (near && near < s->s_hpfs_fs_size)
X if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret;
X if (b != -1) {
- if (b < 0x10000000) if ((sec = alloc_in_bmp(s, b<<14, n, f_p ? forward : forward/2))) goto ret;
- else if ((sec = alloc_in_bmp(s, (b&0xfffffff)<<14, n, f_p ? forward : 0))) goto ret;
+ if ((sec = alloc_in_bmp(s, b<<14, n, f_p ? forward : forward/2))) {
+ b &= 0x0fffffff;
+ goto ret;
+ }
+ if (b > 0x10000000) if ((sec = alloc_in_bmp(s, (b&0xfffffff)<<14, n, f_p ? forward : 0))) goto ret;
X }
X n_bmps = (s->s_hpfs_fs_size + 0x4000 - 1) >> 14;
X for (i = 0; i < n_bmps / 2; i++) {
diff -u --recursive --new-file v2.3.5/linux/fs/hpfs/hpfs_fn.h linux/fs/hpfs/hpfs_fn.h
--- v2.3.5/linux/fs/hpfs/hpfs_fn.h Mon May 17 09:55:22 1999
+++ linux/fs/hpfs/hpfs_fn.h Fri Jun 4 01:06:29 1999
@@ -36,7 +36,7 @@
X #define ANODE_ALLOC_FWD 512
X #define FNODE_ALLOC_FWD 0
X #define ALLOC_FWD_MIN 16
-#define ALLOC_FWD_MAX 512
+#define ALLOC_FWD_MAX 128
X #define ALLOC_M 1
X #define FNODE_RD_AHEAD 16
X #define ANODE_RD_AHEAD 16
diff -u --recursive --new-file v2.3.5/linux/fs/hpfs/namei.c linux/fs/hpfs/namei.c
--- v2.3.5/linux/fs/hpfs/namei.c Wed Jun 2 14:44:39 1999
+++ linux/fs/hpfs/namei.c Fri Jun 4 01:06:29 1999
@@ -482,14 +482,9 @@
X de.hidden = new_name[0] == '.';
X
X if (new_inode) {
- hpfs_brelse4(&qbh);
- if ((nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
- int r;
- if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
- if (!(nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
- hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent #2");
- goto end1;
- }
+ int r;
+ if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
+ if ((nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
X new_inode->i_nlink = 0;
X copy_de(nde, &de);
X memcpy(nde->name, new_name, new_len);
@@ -497,11 +492,11 @@
X hpfs_brelse4(&qbh1);
X goto end;
X }
- err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
+ hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
+ err = -EFSERROR;
X goto end1;
X }
- hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
- err = -EFSERROR;
+ err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
X goto end1;
X }
X
diff -u --recursive --new-file v2.3.5/linux/fs/hpfs/super.c linux/fs/hpfs/super.c
--- v2.3.5/linux/fs/hpfs/super.c Wed Jun 2 14:44:39 1999
+++ linux/fs/hpfs/super.c Tue Jun 8 10:47:58 1999
@@ -528,7 +528,7 @@
X brelse(bh0);
X
X hpfs_lock_iget(s, 1);
- s->s_root = d_alloc_root(iget(s, s->s_hpfs_root), NULL);
+ s->s_root = d_alloc_root(iget(s, s->s_hpfs_root));
X hpfs_unlock_iget(s);
X unlock_super(s);
X if (!s->s_root || !s->s_root->d_inode) {
diff -u --recursive --new-file v2.3.5/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.3.5/linux/fs/isofs/inode.c Mon May 31 22:28:06 1999
+++ linux/fs/isofs/inode.c Tue Jun 8 10:47:58 1999
@@ -835,7 +835,7 @@
X if (!inode->i_op)
X goto out_bad_root;
X /* get the root dentry */
- s->s_root = d_alloc_root(inode, NULL);
+ s->s_root = d_alloc_root(inode);
X if (!(s->s_root))
X goto out_no_root;
X
diff -u --recursive --new-file v2.3.5/linux/fs/minix/bitmap.c linux/fs/minix/bitmap.c
--- v2.3.5/linux/fs/minix/bitmap.c Tue Oct 20 14:08:14 1998
+++ linux/fs/minix/bitmap.c Tue Jun 8 10:47:58 1999
@@ -140,7 +140,7 @@
X if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
X printk("Bad inode number on dev %s: %d is out of range\n",
X kdevname(inode->i_dev), ino);
- return 0;
+ return NULL;
X }
X block = (2 + inode->i_sb->u.minix_sb.s_imap_blocks +
X inode->i_sb->u.minix_sb.s_zmap_blocks +
@@ -148,7 +148,7 @@
X bh = bread(inode->i_dev, block, BLOCK_SIZE);
X if (!bh) {
X printk("unable to read i-node block\n");
- return 0;
+ return NULL;
X }
X raw_inode = ((struct minix_inode *)bh->b_data +
X (ino - 1) % MINIX_INODES_PER_BLOCK);
@@ -168,7 +168,7 @@
X if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
X printk("Bad inode number on dev %s: %d is out of range\n",
X kdevname(inode->i_dev), ino);
- return 0;
+ return NULL;
X }
X block = (2 + inode->i_sb->u.minix_sb.s_imap_blocks +
X inode->i_sb->u.minix_sb.s_zmap_blocks +
@@ -176,7 +176,7 @@
X bh = bread(inode->i_dev, block, BLOCK_SIZE);
X if (!bh) {
X printk("unable to read i-node block\n");
- return 0;
+ return NULL;
X }
X raw_inode = ((struct minix2_inode *) bh->b_data +
X (ino - 1) % MINIX2_INODES_PER_BLOCK);
diff -u --recursive --new-file v2.3.5/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.3.5/linux/fs/minix/inode.c Fri May 14 18:55:25 1999
+++ linux/fs/minix/inode.c Tue Jun 8 10:47:58 1999
@@ -266,7 +266,7 @@
X if (errmsg)
X goto out_bad_root;
X
- s->s_root = d_alloc_root(root_inode, NULL);
+ s->s_root = d_alloc_root(root_inode);
X if (!s->s_root)
X goto out_iput;
X
diff -u --recursive --new-file v2.3.5/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.3.5/linux/fs/minix/namei.c Mon May 17 09:55:23 1999
+++ linux/fs/minix/namei.c Tue Jun 8 10:47:58 1999
@@ -184,12 +184,7 @@
X dir->i_size = block*bh->b_size + offset;
X mark_inode_dirty(dir);
X }
- if (de->inode) {
- if (namecompare(namelen, info->s_namelen, name, de->name)) {
- brelse(bh);
- return -EEXIST;
- }
- } else {
+ if (!de->inode) {
X dir->i_mtime = dir->i_ctime = CURRENT_TIME;
X mark_inode_dirty(dir);
X for (i = 0; i < info->s_namelen ; i++)
diff -u --recursive --new-file v2.3.5/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.5/linux/fs/ncpfs/inode.c Sat May 15 23:46:04 1999
+++ linux/fs/ncpfs/inode.c Tue Jun 8 10:47:58 1999
@@ -431,7 +431,7 @@
X if (!root_inode)
X goto out_no_root;
X DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
- server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL);
+ server->root_dentry = sb->s_root = d_alloc_root(root_inode);
X if (!sb->s_root)
X goto out_no_root;
X server->root_dentry->d_op = &ncp_dentry_operations;
diff -u --recursive --new-file v2.3.5/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.5/linux/fs/nfs/dir.c Fri May 14 18:55:26 1999
+++ linux/fs/nfs/dir.c Tue Jun 8 17:58:03 1999
@@ -14,8 +14,10 @@
X * Following Linus comments on my original hack, this version
X * depends only on the dcache stuff and doesn't touch the inode
X * layer (iput() and friends).
+ * 6 Jun 1999 Cache readdir lookups in the page cache. -DaveM
X */
X
+#define NFS_NEED_XDR_TYPES
X #include <linux/sched.h>
X #include <linux/errno.h>
X #include <linux/stat.h>
@@ -24,31 +26,16 @@
X #include <linux/kernel.h>
X #include <linux/malloc.h>
X #include <linux/mm.h>
-#include <linux/sunrpc/types.h>
+#include <linux/sunrpc/clnt.h>
X #include <linux/nfs_fs.h>
+#include <linux/nfs.h>
+#include <linux/pagemap.h>
X
X #include <asm/segment.h> /* for fs functions */
X
X #define NFS_PARANOIA 1
X /* #define NFS_DEBUG_VERBOSE 1 */
X
-/*
- * Head for a dircache entry. Currently still very simple; when
- * the cache grows larger, we will need a LRU list.
- */
-struct nfs_dirent {
- dev_t dev; /* device number */
- ino_t ino; /* inode number */
- u32 cookie; /* cookie of first entry */
- unsigned short valid : 1, /* data is valid */
- locked : 1; /* entry locked */
- unsigned int size; /* # of entries */
- unsigned long age; /* last used */
- unsigned long mtime; /* last attr stamp */
- wait_queue_head_t wait;
- __u32 * entry; /* three __u32's per entry */
-};
-
X static int nfs_safe_remove(struct dentry *);
X
X static ssize_t nfs_dir_read(struct file *, char *, size_t, loff_t *);
@@ -107,253 +94,326 @@
X return -EISDIR;
X }
X
-static struct nfs_dirent dircache[NFS_MAX_DIRCACHE];
+/* Each readdir response is composed of entries which look
+ * like the following, as per the NFSv2 RFC:
+ *
+ * __u32 not_end zero if end of response
+ * __u32 file ID opaque ino_t
+ * __u32 namelen size of name string
+ * VAR name string the string, padded to modulo 4 bytes
+ * __u32 cookie opaque ID of next entry
+ *
+ * When you hit not_end being zero, the next __u32 is non-zero if
+ * this is the end of the complete set of readdir entires for this
+ * directory. This can be used, for example, to initiate pre-fetch.
+ *
+ * In order to know what to ask the server for, we only need to know
+ * the final cookie of the previous page, and offset zero has cookie
+ * zero, so we cache cookie to page offset translations in chunks.
+ */
+#define COOKIES_PER_CHUNK (8 - ((sizeof(void *) / sizeof(__u32))))
+struct nfs_cookie_table {
+ struct nfs_cookie_table *next;
+ __u32 cookies[COOKIES_PER_CHUNK];
+};
+static kmem_cache_t *nfs_cookie_cachep;
X
-/*
- * We need to do caching of directory entries to prevent an
- * incredible amount of RPC traffic. Only the most recent open
- * directory is cached. This seems sufficient for most purposes.
- * Technically, we ought to flush the cache on close but this is
- * not a problem in practice.
+/* Since a cookie of zero is declared special by the NFS
+ * protocol, we easily can tell if a cookie in an existing
+ * table chunk is valid or not.
X *
- * XXX: Do proper directory caching by stuffing data into the
- * page cache (may require some fiddling for rsize < PAGE_SIZE).
+ * NOTE: The cookies are indexed off-by-one because zero
+ * need not an entry.
X */
+static __inline__ __u32 *find_cookie(struct inode *inode, unsigned long off)
+{
+ static __u32 cookie_zero = 0;
+ struct nfs_cookie_table *p;
+ __u32 *ret;
+
+ if (!off)
+ return &cookie_zero;
+ off -= 1;
+ p = NFS_COOKIES(inode);
+ while(off >= COOKIES_PER_CHUNK && p) {
+ off -= COOKIES_PER_CHUNK;
+ p = p->next;
+ }
+ ret = NULL;
+ if (p) {
+ ret = &p->cookies[off];
+ if (!*ret)
+ ret = NULL;
+ }
+ return ret;
+}
X
-static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+/* Now we cache directories properly, by stuffing the dirent
+ * data directly in the page cache.
+ *
+ * Inode invalidation due to refresh etc. takes care of
+ * _everything_, no sloppy entry flushing logic, no extraneous
+ * copying, network direct to page cache, the way it was meant
+ * to be.
+ *
+ * NOTE: Dirent information verification is done always by the
+ * page-in of the RPC reply, nowhere else, this simplies
+ * things substantially.
+ */
+#define NFS_NAMELEN_ALIGN(__len) ((((__len)+3)>>2)<<2)
+static u32 find_midpoint(__u32 *p, u32 doff)
X {
- struct dentry *dentry = filp->f_dentry;
- struct inode *inode = dentry->d_inode;
- static DECLARE_WAIT_QUEUE_HEAD(readdir_wait);
- wait_queue_head_t *waitp = NULL;
- struct nfs_dirent *cache, *free;
- unsigned long age, dead;
- u32 cookie;
- int ismydir, result;
- int i, j, index = 0;
- __u32 *entry;
- char *name, *start;
+ u32 walk = doff & PAGE_MASK;
X
- dfprintk(VFS, "NFS: nfs_readdir(%s/%s)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ while(*p++ != 0) {
+ __u32 skip;
X
- result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
- if (result < 0)
- goto out;
+ p++; /* skip fileid */
X
- /*
- * Try to find the entry in the cache
- */
-again:
- if (waitp) {
- interruptible_sleep_on(waitp);
- if (signal_pending(current))
- return -ERESTARTSYS;
- waitp = NULL;
+ /* Skip len, name, and cookie. */
+ skip = NFS_NAMELEN_ALIGN(*p++);
+ p += (skip >> 2) + 1;
+ walk += skip + (4 * sizeof(__u32));
+ if (walk >= doff)
+ break;
X }
+ return walk;
+}
X
- cookie = filp->f_pos;
- entry = NULL;
- free = NULL;
- age = ~(unsigned long) 0;
- dead = jiffies - NFS_ATTRTIMEO(inode);
+static int create_cookie(__u32 cookie, unsigned long off, struct inode *inode)
+{
+ struct nfs_cookie_table **cpp;
X
- for (i = 0, cache = dircache; i < NFS_MAX_DIRCACHE; i++, cache++) {
- /*
- dprintk("NFS: dircache[%d] valid %d locked %d\n",
- i, cache->valid, cache->locked);


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

echo 'End of part 18'
echo 'File patch-2.3.6 is continued in part 19'
echo 19 > _shar_seq_.tmp
exit 0

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part20

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


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

if test "$Scheck" != 20; then


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

- (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY));
X
X if (IS_ERR (base)) return NULL;
X
diff -u --recursive --new-file v2.3.5/linux/include/asm-sparc/pcic.h linux/include/asm-sparc/pcic.h
--- v2.3.5/linux/include/asm-sparc/pcic.h Sun Oct 4 10:22:44 1998
+++ linux/include/asm-sparc/pcic.h Wed Jun 9 14:44:26 1999
@@ -1,4 +1,4 @@
-/* $Id: pcic.h,v 1.1 1998/09/22 05:54:39 jj Exp $
+/* $Id: pcic.h,v 1.2 1999/06/03 15:02:51 davem Exp $
X * pcic.h: JavaEngine 1 specific PCI definitions.
X *


X * Copyright (C) 1998 V. Roganov and G. Raiko

@@ -7,6 +7,8 @@
X #ifndef __SPARC_PCIC_H
X #define __SPARC_PCIC_H
X
+#ifndef __ASSEMBLY__
+
X #include <linux/types.h>
X #include <linux/smp.h>
X #include <linux/smp_lock.h>
@@ -21,13 +23,17 @@
X unsigned long pcic_config_space_addr;
X unsigned long pcic_config_space_data;
X struct linux_pbm_info pbm;
+ struct pcic_ca2irq *pcic_imap;
+ int pcic_imdim;
X };
X
X extern unsigned long pcic_alloc_io(unsigned long* addr);
X extern void pcic_probe(void);
X extern void sun4m_pci_init_IRQ(void);
X
-/* Size of PCI Space */
+#endif
+
+/* Size of PCI I/O space which we relocate. */
X #define PCI_SPACE_SIZE 0x1000000 /* 16 MB */
X
X /* PCIC Register Set. */
@@ -50,10 +56,18 @@
X #define PCI_SOFTWARE_INT_CLEAR 0x6a /* 16 bits */
X #define PCI_SOFTWARE_INT_SET 0x6e /* 16 bits */
X #define PCI_SYS_INT_PENDING 0x70 /* 32 bits */
+#define PCI_SYS_INT_PENDING_PIO 0x40000000
+#define PCI_SYS_INT_PENDING_DMA 0x20000000
+#define PCI_SYS_INT_PENDING_PCI 0x10000000
+#define PCI_SYS_INT_PENDING_APSR 0x08000000
X #define PCI_SYS_INT_TARGET_MASK 0x74 /* 32 bits */
X #define PCI_SYS_INT_TARGET_MASK_CLEAR 0x78 /* 32 bits */
X #define PCI_SYS_INT_TARGET_MASK_SET 0x7c /* 32 bits */
X #define PCI_SYS_INT_PENDING_CLEAR 0x83 /* 8 bits */
+#define PCI_SYS_INT_PENDING_CLEAR_ALL 0x80
+#define PCI_SYS_INT_PENDING_CLEAR_PIO 0x40
+#define PCI_SYS_INT_PENDING_CLEAR_DMA 0x20
+#define PCI_SYS_INT_PENDING_CLEAR_PCI 0x10
X #define PCI_IOTLB_CONTROL 0x84 /* 8 bits */
X #define PCI_INT_SELECT_LO 0x88 /* 16 bits */
X #define PCI_ARBITRATION_SELECT 0x8a /* 16 bits */
diff -u --recursive --new-file v2.3.5/linux/include/asm-sparc64/namei.h linux/include/asm-sparc64/namei.h
--- v2.3.5/linux/include/asm-sparc64/namei.h Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc64/namei.h Wed Jun 9 16:24:15 1999
@@ -28,7 +28,7 @@
X
X base = lookup_dentry (emul,
X dget (current->fs->root),
- (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY));
X
X if (IS_ERR (base)) return NULL;
X
diff -u --recursive --new-file v2.3.5/linux/include/linux/cyclomx.h linux/include/linux/cyclomx.h
--- v2.3.5/linux/include/linux/cyclomx.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/cyclomx.h Wed Jun 2 14:40:22 1999
@@ -0,0 +1,91 @@
+/*
+* cyclomx.h CYCLOM X Multiprotocol WAN Link Driver.
+* User-level API definitions.
+*
+* Author: Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+*
+* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Based on wanpipe.h by Gene Kozin <ge...@compuserve.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 (at your option) any later version.
+* ============================================================================
+* 1999/05/19 acme wait_queue_head_t wait_stats(support for 2.3.*)
+* 1999/01/03 acme judicious use of data types
+* Dec 27, 1998 Arnaldo cleanup: PACKED not needed
+* Aug 08, 1998 Arnaldo Version 0.0.1
+*/
+#ifndef _CYCLOMX_H
+#define _CYCLOMX_H
+
+#include <linux/wanrouter.h>
+#include <asm/spinlock.h>
+
+#ifdef __KERNEL__
+/* Kernel Interface */
+
+#include <linux/cycx_drv.h> /* CYCLOM X support module API definitions */
+#include <linux/cycx_cfm.h> /* CYCLOM X firmware module definitions */
+#ifdef CONFIG_CYCLOMX_X25
+#include <linux/cycx_x25.h>
+#endif
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#define is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
+
+/* Adapter Data Space.
+ * This structure is needed because we handle multiple cards, otherwise
+ * static data would do it.
+ */
+typedef struct cycx {
+ char devname[WAN_DRVNAME_SZ+1]; /* card name */
+ cycxhw_t hw; /* hardware configuration */
+ wan_device_t wandev; /* WAN device data space */
+ u32 open_cnt; /* number of open interfaces */
+ u32 state_tick; /* link state timestamp */
+ spinlock_t lock;
+ char in_isr; /* interrupt-in-service flag */
+ char buff_int_mode_unbusy; /* flag for carrying out dev_tint */
+ u16 irq_dis_if_send_count; /* Disabling irqs in if_send*/
+#if LINUX_VERSION_CODE >= 0x020300
+ wait_queue_head_t wait_stats; /* to wait for the STATS indication */
+#else
+ struct wait_queue* wait_stats; /* to wait for the STATS indication */
+#endif
+ u32 mbox; /* -> mailbox */
+ void (*isr)(struct cycx* card); /* interrupt service routine */
+ int (*exec)(struct cycx* card, void* u_cmd, void* u_data);
+ union {
+#ifdef CONFIG_CYCLOMX_X25
+ struct { /* X.25 specific data */
+ u32 lo_pvc;
+ u32 hi_pvc;
+ u32 lo_svc;
+ u32 hi_svc;
+ TX25Stats stats;
+ unsigned critical; /* critical section flag */
+ u32 connection_keys;
+ } x;
+#endif
+ } u;
+} cycx_t;
+
+/* Public Functions */
+void cyclomx_open (cycx_t* card); /* cycx_main.c */
+void cyclomx_close (cycx_t* card); /* cycx_main.c */
+void cyclomx_set_state (cycx_t* card, int state); /* cycx_main.c */
+
+#ifdef CONFIG_CYCLOMX_X25
+int cyx_init (cycx_t* card, wandev_conf_t* conf); /* cycx_x25.c */
+#endif
+#endif /* __KERNEL__ */
+#endif /* _CYCLOMX_H */
diff -u --recursive --new-file v2.3.5/linux/include/linux/cycx_cfm.h linux/include/linux/cycx_cfm.h
--- v2.3.5/linux/include/linux/cycx_cfm.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/cycx_cfm.h Wed Jun 2 14:40:22 1999
@@ -0,0 +1,81 @@
+/*
+* cycx_cfm.h CYCLOM X Multiprotocol WAN Link Driver.
+* Definitions for the CYCLOM X Firmware Module (CFM).
+*
+* Author: Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Based on sdlasfm.h by Gene Kozin <7460...@compuserve.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 (at your option) any later version.
+* ============================================================================
+* Aug 08, 1998 Arnaldo Initial version.
+*/
+#ifndef _CYCX_CFM_H
+#define _CYCX_CFM_H
+
+/* Defines */
+
+#define CFM_VERSION 2
+#define CFM_SIGNATURE "CFM - Cyclades CYCX Firmware Module"
+
+/* min/max */
+#define CFM_IMAGE_SIZE 0x20000 /* max size of CYCX code image file */
+#define CFM_DESCR_LEN 256 /* max length of description string */
+#define CFM_MAX_CYCX 1 /* max number of compatible adapters */
+#define CFM_LOAD_BUFSZ 0x400 /* buffer size for reset code (buffer_load) */
+
+/* Firmware Commands */
+#define GEN_POWER_ON 0x1280
+
+#define GEN_SET_SEG 0x1401 /* boot segment setting. */
+#define GEN_BOOT_DAT 0x1402 /* boot data. */
+#define GEN_START 0x1403 /* board start. */
+#define GEN_DEFPAR 0x1404 /* buffer length for boot. */
+
+/* Adapter types */
+#define CYCX_2X 2
+#define CYCX_8X 8
+#define CYCX_16X 16
+
+#define CFID_X25_2X 5200
+
+
+/* Data Types */
+
+typedef struct cfm_info /* firmware module information */
+{
+ unsigned short codeid; /* firmware ID */
+ unsigned short version; /* firmaware version number */
+ unsigned short adapter[CFM_MAX_CYCX]; /* compatible adapter types */
+ unsigned long memsize; /* minimum memory size */
+ unsigned short reserved[2]; /* reserved */
+ unsigned short startoffs; /* entry point offset */
+ unsigned short winoffs; /* dual-port memory window offset */
+ unsigned short codeoffs; /* code load offset */
+ unsigned long codesize; /* code size */
+ unsigned short dataoffs; /* configuration data load offset */
+ unsigned long datasize; /* configuration data size */
+} cfm_info_t;
+
+typedef struct cfm /* CYCX firmware file structire */
+{
+ char signature[80]; /* CFM file signature */
+ unsigned short version; /* file format version */
+ unsigned short checksum; /* info + image */
+ unsigned short reserved[6]; /* reserved */
+ char descr[CFM_DESCR_LEN]; /* description string */
+ cfm_info_t info; /* firmware module info */
+ unsigned char image[1]; /* code image (variable size) */
+} cfm_t;
+
+typedef struct cycx_header_s {
+ unsigned long reset_size;
+ unsigned long data_size;
+ unsigned long code_size;
+} cycx_header_t;
+
+#endif /* _CYCX_CFM_H */
diff -u --recursive --new-file v2.3.5/linux/include/linux/cycx_drv.h linux/include/linux/cycx_drv.h
--- v2.3.5/linux/include/linux/cycx_drv.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/cycx_drv.h Wed Jun 2 14:40:22 1999
@@ -0,0 +1,66 @@
+/*
+* cycx_drv.h CYCX Support Module. Kernel API Definitions.
+*
+* Author: Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Based on sdladrv.h by Gene Kozin <ge...@compuserve.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 (at your option) any later version.
+* ============================================================================
+* 1999/01/03 acme more judicious use of data types...
+* uclong, ucchar, etc deleted, the u8, u16, u32
+* types are the portable way to go.
+* 1999/01/03 acme judicious use of data types... u16, u32, etc
+* Dec 26, 1998 Arnaldo FIXED_BUFFERS, CONF_OFFSET,
+* removal of cy_read{bwl}
+* Aug 08, 1998 Arnaldo Initial version.
+*/
+#ifndef _CYCX_DRV_H
+#define _CYCX_DRV_H
+
+#define CYCX_WINDOWSIZE 0x4000 /* default dual-port memory window size */
+#define GEN_CYCX_INTR 0x02
+#define RST_ENABLE 0x04
+#define START_CPU 0x06
+#define RST_DISABLE 0x08
+#define FIXED_BUFFERS 0x08
+#define TEST_PATTERN 0xaa55
+#define CMD_OFFSET 0x20
+#define CONF_OFFSET 0x0380
+#define RESET_OFFSET 0x3c00 /* For reset file load */
+#define DATA_OFFSET 0x0100 /* For code and data files load */
+#define START_OFFSET 0x3ff0 /* 80186 starts here */
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* Data Structures */
+/* Adapter hardware configuration. Pointer to this structure is passed to all
+ * APIs. */
+typedef struct cycxhw {
+ u32 type; /* adapter type */
+ u32 fwid; /* firmware ID */
+ int irq; /* interrupt request level */
+ u32 dpmbase; /* dual-port memory base */
+ u32 dpmsize; /* dual-port memory size */
+ u32 pclk; /* CPU clock rate, kHz */
+ u32 memory; /* memory size */
+ u32 reserved[5];
+} cycxhw_t;
+
+/* Function Prototypes */
+extern int cycx_setup (cycxhw_t* hw, void* sfm, u32 len);
+extern int cycx_down (cycxhw_t* hw);
+extern int cycx_inten (cycxhw_t* hw);
+extern int cycx_intde (cycxhw_t* hw);
+extern int cycx_intack (cycxhw_t* hw);
+extern int cycx_intr (cycxhw_t* hw);
+extern int cycx_peek (cycxhw_t* hw, u32 addr, void* buf, u32 len);
+extern int cycx_poke (cycxhw_t* hw, u32 addr, void* buf, u32 len);
+extern int cycx_exec (u32 addr);
+#endif /* _CYCX_DRV_H */
diff -u --recursive --new-file v2.3.5/linux/include/linux/cycx_x25.h linux/include/linux/cycx_x25.h
--- v2.3.5/linux/include/linux/cycx_x25.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/cycx_x25.h Wed Jun 2 14:40:22 1999
@@ -0,0 +1,103 @@
+/*
+* cycx_x25.h Cyclom X.25 firmware API definitions.
+*
+* Author: Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+*
+* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Based on sdla_x25.h by Gene Kozin <7460...@compuserve.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 (at your option) any later version.
+* ============================================================================
+* 1999/01/03 acme judicious use of data types
+*
+* 1999/01/02 acme #define X25_ACK_N3 0x4411
+* Dec 28, 1998 Arnaldo cleanup: lot'o'things removed
+* commands listed,
+* TX25Cmd & TX25Config structs
+* typedef'ed
+*/
+#ifndef _CYCX_X25_H
+#define _CYCX_X25_H
+
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+
+/* X.25 shared memory layout. */
+#define X25_MBOX_OFFS 0x300 /* general mailbox block */
+#define X25_RXMBOX_OFFS 0x340 /* receive mailbox */
+
+/* DATA STRUCTURES */
+/* X.25 Command Block. */
+typedef struct X25Cmd
+{
+ u16 command PACKED;
+ u16 link PACKED; /* values: 0 or 1 */
+ u16 len PACKED; /* values: 0 thru 0x205 (517) */
+ u32 buf PACKED;
+} TX25Cmd;
+
+/* Defines for the 'command' field. */
+#define X25_CONNECT_REQUEST 0x4401
+#define X25_CONNECT_RESPONSE 0x4402
+#define X25_DISCONNECT_REQUEST 0x4403
+#define X25_DISCONNECT_RESPONSE 0x4404
+#define X25_DATA_REQUEST 0x4405
+#define X25_ACK_TO_VC 0x4406
+#define X25_INTERRUPT_RESPONSE 0x4407
+#define X25_CONFIG 0x4408
+#define X25_CONNECT_INDICATION 0x4409
+#define X25_CONNECT_CONFIRM 0x440A
+#define X25_DISCONNECT_INDICATION 0x440B
+#define X25_DISCONNECT_CONFIRM 0x440C
+#define X25_DATA_INDICATION 0x440E
+#define X25_INTERRUPT_INDICATION 0x440F
+#define X25_ACK_FROM_VC 0x4410
+#define X25_ACK_N3 0x4411
+#define X25_CONNECT_COLLISION 0x4413
+#define X25_N3WIN 0x4414
+#define X25_LINE_ON 0x4415
+#define X25_LINE_OFF 0x4416
+#define X25_RESET_REQUEST 0x4417
+#define X25_LOG 0x4500
+#define X25_STATISTIC 0x4600
+#define X25_TRACE 0x4700
+#define X25_N2TRACEXC 0x4702
+#define X25_N3TRACEXC 0x4703
+
+typedef struct X25Config {
+ u8 link PACKED; /* link number */
+ u8 speed PACKED; /* line speed */
+ u8 clock PACKED; /* internal/external */
+ u8 n2 PACKED; /* # of level 2 retransm.(values: 1 thru FF) */
+ u8 n2win PACKED; /* level 2 window (values: 1 thru 7) */
+ u8 n3win PACKED; /* level 3 window (values: 1 thru 7) */
+ u8 nvc PACKED; /* # of logical channels (values: 1 thru 64) */
+ u8 pktlen PACKED; /* level 3 packet lenght - log base 2 of size */
+ u8 locaddr PACKED; /* my address */
+ u8 remaddr PACKED; /* remote address */
+ u16 t1 PACKED; /* time, in seconds */
+ u16 t2 PACKED; /* time, in seconds */
+ u8 t21 PACKED; /* time, in seconds */
+ u8 npvc PACKED; /* # of permanent virt. circuits (1 thru nvc) */
+ u8 t23 PACKED; /* time, in seconds */
+ u8 flags PACKED; /* see dosx25.doc, in portuguese, for details */
+} TX25Config;
+
+typedef struct X25Stats {
+ u16 rx_crc_errors PACKED;
+ u16 rx_over_errors PACKED;
+ u16 n2_tx_frames PACKED;
+ u16 n2_rx_frames PACKED;
+ u16 tx_timeouts PACKED;
+ u16 rx_timeouts PACKED;
+ u16 n3_tx_packets PACKED;
+ u16 n3_rx_packets PACKED;
+ u16 tx_aborts PACKED;
+ u16 rx_aborts PACKED;
+} TX25Stats;
+#endif /* _CYCX_X25_H */
diff -u --recursive --new-file v2.3.5/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.3.5/linux/include/linux/dcache.h Sat May 8 17:56:37 1999
+++ linux/include/linux/dcache.h Tue Jun 8 10:47:58 1999
@@ -12,8 +12,6 @@
X * with heavy changes by Linus Torvalds
X */
X
-#define D_MAXLEN 1024
-
X #define IS_ROOT(x) ((x) == (x)->d_parent)
X
X /*
@@ -132,7 +130,7 @@
X extern void d_delete(struct dentry *);
X
X /* allocate/de-allocate */
-extern struct dentry * d_alloc(struct dentry * parent, const struct qstr *name);
+extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
X extern void prune_dcache(int);
X extern void shrink_dcache_sb(struct super_block *);
X extern void shrink_dcache_parent(struct dentry *);
@@ -147,7 +145,7 @@
X extern void free_inode_memory(int); /* defined in fs/inode.c */
X
X /* only used at mount-time */
-extern struct dentry * d_alloc_root(struct inode * root_inode, struct dentry * old_root);
+extern struct dentry * d_alloc_root(struct inode *);
X
X /* test whether root is busy without destroying dcache */
X extern int is_root_busy(struct dentry *);
@@ -155,7 +153,7 @@
X /*
X * This adds the entry to the hash queues.
X */
-extern void d_rehash(struct dentry * entry);
+extern void d_rehash(struct dentry *);
X /*
X * This adds the entry to the hash queues and initializes "d_inode".
X * The entry was actually filled in earlier during "d_alloc()"
@@ -167,17 +165,16 @@
X }
X
X /* used for rename() and baskets */
-extern void d_move(struct dentry * entry, struct dentry * newdentry);
+extern void d_move(struct dentry *, struct dentry *);
X
X /* appendix may either be NULL or be used for transname suffixes */
-extern struct dentry * d_lookup(struct dentry * dir, struct qstr * name);
+extern struct dentry * d_lookup(struct dentry *, struct qstr *);
X
X /* validate "insecure" dentry pointer */
-extern int d_validate(struct dentry *dentry, struct dentry *dparent,
- unsigned int hash, unsigned int len);
+extern int d_validate(struct dentry *, struct dentry *, unsigned int, unsigned int);
X
X /* write full pathname into buffer and return start of pathname */
-extern char * d_path(struct dentry * entry, char * buf, int buflen);
+extern char * d_path(struct dentry *, char *, int);
X
X /* Allocation counts.. */
X static __inline__ struct dentry * dget(struct dentry *dentry)
diff -u --recursive --new-file v2.3.5/linux/include/linux/file.h linux/include/linux/file.h
--- v2.3.5/linux/include/linux/file.h Sat Jan 9 19:16:44 1999
+++ linux/include/linux/file.h Tue Jun 8 10:47:58 1999
@@ -44,7 +44,7 @@
X /*
X * Install a file pointer in the fd array.
X */
-extern inline void fd_install(unsigned int fd, struct file *file)
+extern inline void fd_install(unsigned int fd, struct file * file)
X {
X current->files->fd[fd] = file;
X }
@@ -65,7 +65,7 @@
X * I suspect there are many other similar "optimizations" across the
X * kernel...
X */
-extern void fput(struct file *file);
-extern void put_filp(struct file *file);
+extern void fput(struct file *);
+extern void put_filp(struct file *);
X
-#endif
+#endif /* __LINUX_FILE_H */
diff -u --recursive --new-file v2.3.5/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.5/linux/include/linux/fs.h Wed Jun 2 14:44:39 1999
+++ linux/include/linux/fs.h Tue Jun 8 23:03:41 1999
@@ -103,7 +103,8 @@
X /*
X * Flags that can be altered by MS_REMOUNT
X */
-#define MS_RMT_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME)
+#define MS_RMT_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|\
+ MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME)
X
X /*
X * Magic mount flag number. Has to be or-ed to the flag values.
@@ -112,7 +113,7 @@
X #define MS_MGC_MSK 0xffff0000 /* magic flag number mask */
X
X /*
- * Note that read-only etc flags are inode-specific: setting some file-system
+ * Note that nosuid etc flags are inode-specific: setting some file-system
X * flags just means all the inodes inherit those flags by default. It might be
X * possible to override it selectively if you really wanted to with some
X * ioctl() that is not currently implemented.
@@ -171,9 +172,8 @@
X
X #include <asm/semaphore.h>
X #include <asm/byteorder.h>
-#include <asm/bitops.h>
X
-extern void update_atime (struct inode *inode);
+extern void update_atime (struct inode *);
X #define UPDATE_ATIME(inode) update_atime (inode)
X
X extern void buffer_init(unsigned long);
@@ -233,8 +233,7 @@
X };
X
X typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
-void init_buffer(struct buffer_head *bh, kdev_t dev, int block,
- bh_end_io_t *handler, void *dev_id);
+void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *);
X
X static inline int buffer_uptodate(struct buffer_head * bh)
X {
@@ -480,19 +479,17 @@
X
X #include <linux/fcntl.h>
X
-extern int fcntl_getlk(unsigned int fd, struct flock *l);
-extern int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l);
+extern int fcntl_getlk(unsigned int, struct flock *);
+extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);
X
X /* fs/locks.c */
-extern void locks_remove_posix(struct file *, fl_owner_t id);
+extern void locks_remove_posix(struct file *, fl_owner_t);
X extern void locks_remove_flock(struct file *);
X extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
X extern int posix_lock_file(struct file *, struct file_lock *, unsigned int);
X extern void posix_block_lock(struct file_lock *, struct file_lock *);
X extern void posix_unblock_lock(struct file_lock *);
X
-#include <linux/stat.h>
-
X struct fasync_struct {
X int magic;
X int fa_fd;
@@ -667,10 +664,8 @@
X #define FLOCK_VERIFY_READ 1
X #define FLOCK_VERIFY_WRITE 2
X
-extern int locks_mandatory_locked(struct inode *inode);
-extern int locks_mandatory_area(int read_write, struct inode *inode,
- struct file *filp, loff_t offset,
- size_t count);
+extern int locks_mandatory_locked(struct inode *);
+extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t);
X
X extern inline int locks_verify_locked(struct inode *inode)
X {
@@ -709,35 +704,35 @@
X extern struct file *filp_open(const char *, int, int);
X extern int filp_close(struct file *, fl_owner_t id);
X
-extern char * getname(const char * filename);
+extern char * getname(const char *);
X #define __getname() ((char *) __get_free_page(GFP_KERNEL))
X #define putname(name) free_page((unsigned long)(name))
X
-extern void kill_fasync(struct fasync_struct *fa, int sig);
+extern void kill_fasync(struct fasync_struct *, int);
X extern int register_blkdev(unsigned int, const char *, struct file_operations *);
-extern int unregister_blkdev(unsigned int major, const char * name);
-extern int blkdev_open(struct inode * inode, struct file * filp);
-extern int blkdev_release (struct inode * inode);
+extern int unregister_blkdev(unsigned int, const char *);
+extern int blkdev_open(struct inode *, struct file *);
+extern int blkdev_release (struct inode *);
X extern struct file_operations def_blk_fops;
X extern struct inode_operations blkdev_inode_operations;
X
X /* fs/devices.c */
X extern int register_chrdev(unsigned int, const char *, struct file_operations *);
-extern int unregister_chrdev(unsigned int major, const char * name);
-extern int chrdev_open(struct inode * inode, struct file * filp);
+extern int unregister_chrdev(unsigned int, const char *);
+extern int chrdev_open(struct inode *, struct file *);
X extern struct file_operations def_chr_fops;
X extern struct inode_operations chrdev_inode_operations;
-extern char * bdevname(kdev_t dev);
-extern char * cdevname(kdev_t dev);
-extern char * kdevname(kdev_t dev);
+extern char * bdevname(kdev_t);
+extern char * cdevname(kdev_t);
+extern char * kdevname(kdev_t);
X extern void init_special_inode(struct inode *, umode_t, int);
X
-extern void init_fifo(struct inode * inode);
+extern void init_fifo(struct inode *);
X extern struct inode_operations fifo_inode_operations;
X
X /* Invalid inode operations -- fs/bad_inode.c */
-extern void make_bad_inode(struct inode * inode);
-extern int is_bad_inode(struct inode * inode);
+extern void make_bad_inode(struct inode *);
+extern int is_bad_inode(struct inode *);
X
X extern struct file_operations connecting_fifo_fops;
X extern struct file_operations read_fifo_fops;
@@ -747,15 +742,15 @@
X extern struct file_operations write_pipe_fops;
X extern struct file_operations rdwr_pipe_fops;
X
-extern struct file_system_type *get_fs_type(const char *name);
+extern struct file_system_type *get_fs_type(const char *);
X
X extern int fs_may_remount_ro(struct super_block *);
-extern int fs_may_mount(kdev_t dev);
+extern int fs_may_mount(kdev_t);
X
X extern struct file *inuse_filps;
X
-extern void refile_buffer(struct buffer_head * buf);
-extern void set_writetime(struct buffer_head * buf, int flag);
+extern void refile_buffer(struct buffer_head *);
+extern void set_writetime(struct buffer_head *, int);
X extern int try_to_free_buffers(struct page *);
X
X extern int nr_buffers;
@@ -767,7 +762,7 @@
X #define BUF_DIRTY 2 /* Dirty buffers, not yet scheduled for write */
X #define NR_LIST 3
X
-void mark_buffer_uptodate(struct buffer_head * bh, int on);
+void mark_buffer_uptodate(struct buffer_head *, int);
X
X extern inline void mark_buffer_clean(struct buffer_head * bh)
X {
@@ -786,23 +781,23 @@
X }
X }
X
-extern int check_disk_change(kdev_t dev);
-extern int invalidate_inodes(struct super_block * sb);
+extern int check_disk_change(kdev_t);
+extern int invalidate_inodes(struct super_block *);
X extern void invalidate_inode_pages(struct inode *);
-extern void invalidate_buffers(kdev_t dev);
-extern int floppy_is_wp(int minor);
-extern void sync_inodes(kdev_t dev);
-extern void write_inode_now(struct inode *inode);
-extern void sync_dev(kdev_t dev);
-extern int fsync_dev(kdev_t dev);
-extern void sync_supers(kdev_t dev);
-extern int bmap(struct inode * inode,int block);
+extern void invalidate_buffers(kdev_t);
+extern int floppy_is_wp(int);
+extern void sync_inodes(kdev_t);
+extern void write_inode_now(struct inode *);
+extern void sync_dev(kdev_t);
+extern int fsync_dev(kdev_t);
+extern void sync_supers(kdev_t);
+extern int bmap(struct inode *, int);
X extern int notify_change(struct dentry *, struct iattr *);
-extern int permission(struct inode * inode,int mask);
-extern int get_write_access(struct inode *inode);
-extern void put_write_access(struct inode *inode);
-extern struct dentry * open_namei(const char * pathname, int flag, int mode);
-extern struct dentry * do_mknod(const char * filename, int mode, dev_t dev);
+extern int permission(struct inode *, int);
+extern int get_write_access(struct inode *);
+extern void put_write_access(struct inode *);
+extern struct dentry * open_namei(const char *, int, int);
+extern struct dentry * do_mknod(const char *, int, dev_t);
X extern int do_pipe(int *);
X
X /* fs/dcache.c -- generic fs support functions */
@@ -840,7 +835,7 @@
X #define lnamei(pathname) __namei(pathname, 0)
X
X extern void iput(struct inode *);
-extern struct inode * igrab(struct inode *inode);
+extern struct inode * igrab(struct inode *);
X extern ino_t iunique(struct super_block *, ino_t);
X extern struct inode * iget(struct super_block *, unsigned long);
X extern void clear_inode(struct inode *);
@@ -851,7 +846,7 @@
X extern struct file * get_empty_filp(void);
X extern struct buffer_head * get_hash_table(kdev_t, int, int);
X extern struct buffer_head * getblk(kdev_t, int, int);
-extern struct buffer_head * find_buffer(kdev_t dev, int block, int size);
+extern struct buffer_head * find_buffer(kdev_t, int, int);
X extern void ll_rw_block(int, int, struct buffer_head * bh[]);
X extern int is_read_only(kdev_t);
X extern void __brelse(struct buffer_head *);
@@ -860,17 +855,16 @@
X if (buf)
X __brelse(buf);
X }
-extern void __bforget(struct buffer_head *buf);
+extern void __bforget(struct buffer_head *);
X extern inline void bforget(struct buffer_head *buf)
X {
X if (buf)
X __bforget(buf);
X }
-extern void set_blocksize(kdev_t dev, int size);
-extern unsigned int get_hardblocksize(kdev_t dev);
-extern struct buffer_head * bread(kdev_t dev, int block, int size);
-extern struct buffer_head * breada(kdev_t dev,int block, int size,
- unsigned int pos, unsigned int filesize);
+extern void set_blocksize(kdev_t, int);
+extern unsigned int get_hardblocksize(kdev_t);
+extern struct buffer_head * bread(kdev_t, int, int);
+extern struct buffer_head * breada(kdev_t, int, int, unsigned int, unsigned int);
X
X extern int brw_page(int, struct page *, kdev_t, int [], int, int);
X
@@ -879,12 +873,12 @@
X extern int generic_readpage(struct file *, struct page *);
X extern int generic_file_mmap(struct file *, struct vm_area_struct *);
X extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
-extern ssize_t generic_file_write(struct file *, const char*, size_t, loff_t *, writepage_t);
+extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *, writepage_t);
X
-extern struct super_block *get_super(kdev_t dev);
-extern void put_super(kdev_t dev);
-unsigned long generate_cluster(kdev_t dev, int b[], int size);
-unsigned long generate_cluster_swab32(kdev_t dev, int b[], int size);
+extern struct super_block *get_super(kdev_t);
+extern void put_super(kdev_t);
+unsigned long generate_cluster(kdev_t, int b[], int);
+unsigned long generate_cluster_swab32(kdev_t, int b[], int);
X extern kdev_t ROOT_DEV;
X
X extern void show_buffers(void);
@@ -892,7 +886,7 @@
X
X #ifdef CONFIG_BLK_DEV_INITRD
X extern kdev_t real_root_dev;
-extern int change_root(kdev_t new_root_dev,const char *put_old);
+extern int change_root(kdev_t, const char *);
X #endif
X
X extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
@@ -902,8 +896,8 @@
X extern ssize_t char_write(struct file *, const char *, size_t, loff_t *);
X extern ssize_t block_write(struct file *, const char *, size_t, loff_t *);
X
-extern int block_fsync(struct file *, struct dentry *dir);
-extern int file_fsync(struct file *, struct dentry *dir);
+extern int block_fsync(struct file *, struct dentry *);
+extern int file_fsync(struct file *, struct dentry *);
X
X extern int inode_change_ok(struct inode *, struct iattr *);
X extern void inode_setattr(struct inode *, struct iattr *);
@@ -914,4 +908,4 @@
X
X #endif /* __KERNEL__ */
X
-#endif
+#endif /* _LINUX_FS_H */
diff -u --recursive --new-file v2.3.5/linux/include/linux/i2o.h linux/include/linux/i2o.h
--- v2.3.5/linux/include/linux/i2o.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/i2o.h Wed Jun 2 14:40:22 1999
@@ -0,0 +1,588 @@
+#ifndef _I2O_H
+#define _I2O_H
+
+/*
+ * Tunable parameters first
+ */
+
+/* How many different OSM's are we allowing */
+#define MAX_I2O_MODULES 64
+/* How many controllers are we allowing */
+#define MAX_I2O_CONTROLLERS 32
+
+
+#ifdef __KERNEL__ /* ioctl stuff only thing exported to users */
+
+/*
+ * I2O Interface Objects
+ */
+
+#include <linux/notifier.h>
+#include <asm/atomic.h>
+
+/*
+ * message structures
+ */
+
+#define TID_SZ 12
+#define FUNCTION_SZ 8
+
+struct i2o_message
+{
+ u32 version_size;
+ u32 function_addr;
+ u32 initiator_context;
+ /* List follows */
+};
+
+
+/*
+ * Each I2O device entity has one or more of these. There is one
+ * per device. *FIXME* how to handle multiple types on one unit.
+ */
+
+struct i2o_device
+{
+ int class; /* Block, Net, SCSI etc (from spec) */
+ int subclass; /* eth, fddi, tr etc (from spec) */
+ int id; /* I2O ID assigned by the controller */
+ int parent; /* Parent device */
+ int flags; /* Control flags */
+ int i2oversion; /* I2O version supported. Actually there
+ * should be high and low version */
+ struct proc_dir_entry* proc_entry; /* /proc dir */
+ struct i2o_driver *owner; /* Owning device */
+ struct i2o_controller *controller; /* Controlling IOP */
+ struct i2o_device *next; /* Chain */
+ char dev_name[8]; /* linux /dev name if available */
+};
+
+/*
+ * Resource data for each PCI I2O controller
+ */
+
+struct i2o_pci
+{
+ int irq;
+};
+
+/*
+ * Each I2O controller has one of these objects
+ */
+
+struct i2o_controller
+{
+ char name[16];
+ int unit;
+ int status; /* I2O status */
+ int i2oversion;
+ int type;
+#define I2O_TYPE_PCI 0x01 /* PCI I2O controller */
+ struct notifier_block *event_notifer; /* Events */
+ atomic_t users;
+ struct i2o_device *devices; /* I2O device chain */
+ struct i2o_controller *next; /* Controller chain */
+ volatile u32 *post_port; /* Messaging ports */
+ volatile u32 *reply_port;
+ volatile u32 *irq_mask; /* Interrupt port */
+ u32 mem_offset; /* MFA offset */
+ u32 mem_phys; /* MFA physical */
+ u32 priv_mem;
+ u32 priv_mem_size;
+ u32 priv_io;
+ u32 priv_io_size;
+
+ struct proc_dir_entry* proc_entry; /* /proc dir */
+
+ union
+ { /* Bus information */
+ struct i2o_pci pci;
+ } bus;
+ void (*destructor)(struct i2o_controller *); /* Bus specific destructor */
+ int (*bind)(struct i2o_controller *, struct i2o_device *); /* Bus specific attach/detach */
+ int (*unbind)(struct i2o_controller *, struct i2o_device *);
+ void *page_frame; /* Message buffers */
+ int inbound_size; /* Inbound queue size */
+};
+
+struct i2o_handler
+{
+ void (*reply)(struct i2o_handler *, struct i2o_controller *, struct i2o_message *);
+ char *name;
+ int context; /* Low 8 bits of the transaction info */
+ /* User data follows */
+};
+
+/*
+ * Messenger inlines
+ */
+
+extern inline u32 I2O_POST_READ32(struct i2o_controller *c)
+{
+ return *c->post_port;
+}
+
+extern inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 Val)
+{
+ *c->post_port = Val;
+}
+
+
+extern inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
+{
+ return *c->reply_port;
+}
+
+extern inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 Val)
+{
+ *c->reply_port= Val;
+}
+
+
+extern inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
+{
+ return *c->irq_mask;
+}
+
+extern inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 Val)
+{
+ *c->irq_mask = Val;
+}
+
+
+extern inline void i2o_post_message(struct i2o_controller *c, u32 m)
+{
+ /* The second line isnt spurious - thats forcing PCI posting */
+ I2O_POST_WRITE32(c,m);
+ (void) I2O_IRQ_READ32(c);
+}
+
+extern inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
+{
+ I2O_REPLY_WRITE32(c,m);
+}
+
+
+struct i2o_controller *i2o_controller_chain;
+
+extern int i2o_quiesce_controller(struct i2o_controller *);
+extern int i2o_clear_controller(struct i2o_controller *);
+extern int i2o_install_controller(struct i2o_controller *);
+extern int i2o_delete_controller(struct i2o_controller *);
+extern int i2o_activate_controller(struct i2o_controller *);
+extern void i2o_unlock_controller(struct i2o_controller *);
+extern struct i2o_controller *i2o_find_controller(int);
+extern int i2o_num_controllers;
+
+extern int i2o_install_handler(struct i2o_handler *);
+extern int i2o_remove_handler(struct i2o_handler *);
+
+extern int i2o_install_device(struct i2o_controller *, struct i2o_device *);
+extern int i2o_delete_device(struct i2o_device *);
+extern int i2o_claim_device(struct i2o_device *, struct i2o_driver *);
+extern int i2o_release_device(struct i2o_device *);
+
+extern int i2o_post_this(struct i2o_controller *, int, u32 *, int);
+extern int i2o_post_wait(struct i2o_controller *, int, u32 *, int, int *, int);
+extern int i2o_issue_claim(struct i2o_controller *, int, int, int, int *);
+extern int i2o_query_scalar(struct i2o_controller *, int, int, int, int, void *,
+ int, int *);
+extern int i2o_params_set(struct i2o_controller *c, int, int, int, int, void *,
+ int, int *);
+
+extern void i2o_run_queue(struct i2o_controller *);
+
+extern void i2o_report_status(const char *, const char *, u8, u8, u16);
+extern void report_common_status(u8);
+extern void report_lan_dsc(u16);
+
+extern u32 i2o_wait_message(struct i2o_controller *, char *);
+
+extern const char *i2o_get_class_name(int);
+
+
+/*
+ * I2O classes / subclasses
+ */
+
+/* Class ID and Code Assignments
+ * (LCT.ClassID.Version field)
+ */
+#define I2O_CLASS_VERSION_10 0x00
+#define I2O_CLASS_VERSION_11 0x01
+
+/* Class code names
+ * (from v1.5 Table 6-1 Class Code Assignments.)
+ */
+
+#define I2O_CLASS_EXECUTIVE 0x000
+#define I2O_CLASS_DDM 0x001
+#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010
+#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011
+#define I2O_CLASS_LAN 0x020
+#define I2O_CLASS_WAN 0x030
+#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040
+#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041
+#define I2O_CLASS_SCSI_PERIPHERAL 0x051
+#define I2O_CLASS_ATE_PORT 0x060
+#define I2O_CLASS_ATE_PERIPHERAL 0x061
+#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
+#define I2O_CLASS_FLOPPY_DEVICE 0x071
+#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
+#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
+#define I2O_CLASS_PEER_TRANSPORT 0x091
+
+/* Rest of 0x092 - 0x09f reserved for peer-to-peer classes
+ */
+
+#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff
+
+/* Subclasses
+ */
+
+#define I2O_SUBCLASS_i960 0x001
+#define I2O_SUBCLASS_HDM 0x020
+#define I2O_SUBCLASS_ISM 0x021
+
+/* Operation functions */
+
+#define I2O_PARAMS_FIELD_GET 0x0001
+#define I2O_PARAMS_LIST_GET 0x0002
+#define I2O_PARAMS_MORE_GET 0x0003
+#define I2O_PARAMS_SIZE_GET 0x0004
+#define I2O_PARAMS_TABLE_GET 0x0005
+#define I2O_PARAMS_FIELD_SET 0x0006
+#define I2O_PARAMS_LIST_SET 0x0007
+#define I2O_PARAMS_ROW_ADD 0x0008
+#define I2O_PARAMS_ROW_DELETE 0x0009
+#define I2O_PARAMS_TABLE_CLEAR 0x000A
+
+/*
+ * I2O serial number conventions / formats
+ * (circa v1.5)
+ */
+
+#define I2O_SNFORMAT_UNKNOWN 0
+#define I2O_SNFORMAT_BINARY 1
+#define I2O_SNFORMAT_ASCII 2
+#define I2O_SNFORMAT_UNICODE 3
+#define I2O_SNFORMAT_LAN48_MAC 4
+#define I2O_SNFORMAT_WAN 5
+
+/* Plus new in v2.0 (Yellowstone pdf doc)
+ */
+
+#define I2O_SNFORMAT_LAN64_MAC 6
+#define I2O_SNFORMAT_DDM 7
+#define I2O_SNFORMAT_IEEE_REG64 8
+#define I2O_SNFORMAT_IEEE_REG128 9
+#define I2O_SNFORMAT_UNKNOWN2 0xff
+
+
+/*
+ * "Special" TID assignments
+ */
+#define I2O_IOP_TID 0
+#define I2O_HOST_TID 1
+
+
+/* Transaction Reply Lists (TRL) Control Word structure */
+
+#define TRL_SINGLE_FIXED_LENGTH 0x00
+#define TRL_SINGLE_VARIABLE_LENGTH 0x40
+#define TRL_MULTIPLE_FIXED_LENGTH 0x80
+
+/* LAN Class specific functions */
+
+#define LAN_PACKET_SEND 0x3B
+#define LAN_SDU_SEND 0x3D
+#define LAN_RECEIVE_POST 0x3E
+#define LAN_RESET 0x35
+#define LAN_SUSPEND 0x37
+
+/*
+ * Messaging API values
+ */
+
+#define I2O_CMD_ADAPTER_ASSIGN 0xB3
+#define I2O_CMD_ADAPTER_READ 0xB2
+#define I2O_CMD_ADAPTER_RELEASE 0xB5
+#define I2O_CMD_BIOS_INFO_SET 0xA5
+#define I2O_CMD_BOOT_DEVICE_SET 0xA7
+#define I2O_CMD_CONFIG_VALIDATE 0xBB
+#define I2O_CMD_CONN_SETUP 0xCA
+#define I2O_CMD_DDM_DESTROY 0xB1
+#define I2O_CMD_DDM_ENABLE 0xD5
+#define I2O_CMD_DDM_QUIESCE 0xC7
+#define I2O_CMD_DDM_RESET 0xD9
+#define I2O_CMD_DDM_SUSPEND 0xAF
+#define I2O_CMD_DEVICE_ASSIGN 0xB7
+#define I2O_CMD_DEVICE_RELEASE 0xB9
+#define I2O_CMD_HRT_GET 0xA8
+#define I2O_CMD_ADAPTER_CLEAR 0xBE
+#define I2O_CMD_ADAPTER_CONNECT 0xC9
+#define I2O_CMD_ADAPTER_RESET 0xBD
+#define I2O_CMD_LCT_NOTIFY 0xA2
+#define I2O_CMD_OUTBOUND_INIT 0xA1
+#define I2O_CMD_PATH_ENABLE 0xD3
+#define I2O_CMD_PATH_QUIESCE 0xC5
+#define I2O_CMD_PATH_RESET 0xD7
+#define I2O_CMD_STATIC_MF_CREATE 0xDD
+#define I2O_CMD_STATIC_MF_RELEASE 0xDF
+#define I2O_CMD_STATUS_GET 0xA0
+#define I2O_CMD_SW_DOWNLOAD 0xA9
+#define I2O_CMD_SW_UPLOAD 0xAB
+#define I2O_CMD_SW_REMOVE 0xAD
+#define I2O_CMD_SYS_ENABLE 0xD1
+#define I2O_CMD_SYS_MODIFY 0xC1
+#define I2O_CMD_SYS_QUIESCE 0xC3
+#define I2O_CMD_SYS_TAB_SET 0xA3
+
+#define I2O_CMD_UTIL_NOP 0x00
+#define I2O_CMD_UTIL_ABORT 0x01
+#define I2O_CMD_UTIL_CLAIM 0x09
+#define I2O_CMD_UTIL_RELEASE 0x0B
+#define I2O_CMD_UTIL_PARAMS_GET 0x06
+#define I2O_CMD_UTIL_PARAMS_SET 0x05
+#define I2O_CMD_UTIL_EVT_REGISTER 0x13
+#define I2O_CMD_UTIL_ACK 0x14
+#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10
+#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D
+#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F
+#define I2O_CMD_UTIL_LOCK 0x17
+#define I2O_CMD_UTIL_LOCK_RELEASE 0x19
+#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15
+
+#define I2O_CMD_SCSI_EXEC 0x81
+#define I2O_CMD_SCSI_ABORT 0x83
+#define I2O_CMD_SCSI_BUSRESET 0x27
+
+#define I2O_CMD_BLOCK_READ 0x30
+#define I2O_CMD_BLOCK_WRITE 0x31
+#define I2O_CMD_BLOCK_CFLUSH 0x37
+#define I2O_CMD_BLOCK_MLOCK 0x49
+#define I2O_CMD_BLOCK_MUNLOCK 0x4B
+#define I2O_CMD_BLOCK_MMOUNT 0x41
+#define I2O_CMD_BLOCK_MEJECT 0x43
+
+#define I2O_PRIVATE_MSG 0xFF
+
+/*
+ * Init Outbound Q status
+ */
+
+#define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01
+#define I2O_CMD_OUTBOUND_INIT_REJECTED 0x02
+#define I2O_CMD_OUTBOUND_INIT_FAILED 0x03
+#define I2O_CMD_OUTBOUND_INIT_COMPLETE 0x04
+
+/*
+ * I2O Get Status State values
+ */
+
+#define ADAPTER_STATE_INITIALIZING 0x01
+#define ADAPTER_STATE_RESET 0x02
+#define ADAPTER_STATE_HOLD 0x04
+#define ADAPTER_STATE_READY 0x05
+#define ADAPTER_STATE_OPERATIONAL 0x08
+#define ADAPTER_STATE_FAILED 0x10
+#define ADAPTER_STATE_FAULTED 0x11
+
+/* I2O API function return values */
+
+#define I2O_RTN_NO_ERROR 0
+#define I2O_RTN_NOT_INIT 1
+#define I2O_RTN_FREE_Q_EMPTY 2
+#define I2O_RTN_TCB_ERROR 3
+#define I2O_RTN_TRANSACTION_ERROR 4
+#define I2O_RTN_ADAPTER_ALREADY_INIT 5
+#define I2O_RTN_MALLOC_ERROR 6
+#define I2O_RTN_ADPTR_NOT_REGISTERED 7
+#define I2O_RTN_MSG_REPLY_TIMEOUT 8
+#define I2O_RTN_NO_STATUS 9
+#define I2O_RTN_NO_FIRM_VER 10
+#define I2O_RTN_NO_LINK_SPEED 11
+
+/* Reply message status defines for all messages */
+
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
+#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
+#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
+#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
+#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08
+#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09
+#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A
+#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B
+#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
+
+/* Status codes and Error Information for Parameter functions */
+
+#define I2O_PARAMS_STATUS_SUCCESS 0x00
+#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01
+#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
+#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03
+#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04
+#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05
+#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06
+#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07
+#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08
+#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09
+#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A
+#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B
+#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C
+#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D
+#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E
+#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F
+#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10
+
+/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error
+ * messages: Table 3-2 Detailed Status Codes.*/
+
+#define I2O_DSC_SUCCESS 0x0000
+#define I2O_DSC_BAD_KEY 0x0002
+#define I2O_DSC_TCL_ERROR 0x0003
+#define I2O_DSC_REPLY_BUFFER_FULL 0x0004
+#define I2O_DSC_NO_SUCH_PAGE 0x0005
+#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006
+#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007
+#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009
+#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A
+#define I2O_DSC_DEVICE_LOCKED 0x000B
+#define I2O_DSC_DEVICE_RESET 0x000C
+#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D
+#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E
+#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F
+#define I2O_DSC_INVALID_OFFSET 0x0010
+#define I2O_DSC_INVALID_PARAMETER 0x0011
+#define I2O_DSC_INVALID_REQUEST 0x0012
+#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013
+#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014
+#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015
+#define I2O_DSC_MISSING_PARAMETER 0x0016
+#define I2O_DSC_TIMEOUT 0x0017
+#define I2O_DSC_UNKNOWN_ERROR 0x0018
+#define I2O_DSC_UNKNOWN_FUNCTION 0x0019
+#define I2O_DSC_UNSUPPORTED_VERSION 0x001A
+#define I2O_DSC_DEVICE_BUSY 0x001B
+#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C
+
+/* Message header defines for VersionOffset */
+#define I2OVER15 0x0001
+#define I2OVER20 0x0002
+/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */
+#define I2OVERSION I2OVER15
+#define SGL_OFFSET_0 I2OVERSION
+#define SGL_OFFSET_4 (0x0040 | I2OVERSION)
+#define SGL_OFFSET_5 (0x0050 | I2OVERSION)
+#define SGL_OFFSET_6 (0x0060 | I2OVERSION)
+#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
+#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
+
+#define TRL_OFFSET_5 (0x0050 | I2OVERSION)
+#define TRL_OFFSET_6 (0x0060 | I2OVERSION)
+
+ /* msg header defines for MsgFlags */
+#define MSG_STATIC 0x0100
+#define MSG_64BIT_CNTXT 0x0200
+#define MSG_MULTI_TRANS 0x1000
+#define MSG_FAIL 0x2000
+#define MSG_LAST 0x4000
+#define MSG_REPLY 0x8000
+
+ /* normal LAN request message MsgFlags and VersionOffset (0x1041) */
+#define LAN_MSG_REQST (MSG_MULTI_TRANS | SGL_OFFSET_4)
+
+ /* minimum size msg */
+#define THREE_WORD_MSG_SIZE 0x00030000
+#define FOUR_WORD_MSG_SIZE 0x00040000
+#define FIVE_WORD_MSG_SIZE 0x00050000
+#define SIX_WORD_MSG_SIZE 0x00060000
+#define SEVEN_WORD_MSG_SIZE 0x00070000
+#define EIGHT_WORD_MSG_SIZE 0x00080000
+#define NINE_WORD_MSG_SIZE 0x00090000
+#define TEN_WORD_MSG_SIZE 0x000A0000
+#define I2O_MESSAGE_SIZE(x) ((x)<<16)
+
+
+/* Special TID Assignments */
+
+#define ADAPTER_TID 0
+#define HOST_TID 1
+
+#define MSG_FRAME_SIZE 128
+#define NMBR_MSG_FRAMES 128
+
+#define MSG_POOL_SIZE 16384
+
+#define I2O_POST_WAIT_OK 1
+#define I2O_POST_WAIT_TIMEOUT -1
+
+#endif /* __KERNEL__ */
+
+#include <asm/ioctl.h>
+
+/*
+ * I2O Control IOCTLs and structures
+ */
+#define I2O_MAGIC_NUMBER 'i'
+#define I2OGETIOPS _IO(I2O_MAGIC_NUMBER,0)
+#define I2OHRTGET _IO(I2O_MAGIC_NUMBER,1)
+#define I2OLCTGET _IO(I2O_MAGIC_NUMBER,2)
+#define I2OPARMSET _IO(I2O_MAGIC_NUMBER,3)
+#define I2OPARMGET _IO(I2O_MAGIC_NUMBER,4)
+#define I2OSWDL _IO(I2O_MAGIC_NUMBER,5)
+#define I2OSWUL _IO(I2O_MAGIC_NUMBER,6)
+#define I2OSWDEL _IO(I2O_MAGIC_NUMBER,7)
+#define I2OHTML _IO(I2O_MAGIC_NUMBER,8)
+
+/* On hold until we figure this out
+#define I2OEVTREG _IO(I2O_MAGIC_NUMBER,9)
+#define I2OEVTCLR _IO(I2O_MAGIC_NUMBER,10)
+#define I2OEVTGET _IO(I2O_MAGIC_NUMBER,11)
+ */
+
+struct i2o_cmd_hrtlct
+{
+ unsigned int iop; /* IOP unit number */


+ void *resbuf; /* Buffer for result */

+ unsigned int *reslen; /* Buffer length in bytes */
+};
+
+
+struct i2o_cmd_psetget
+{
+ unsigned int iop; /* IOP unit number */
+ unsigned int tid; /* Target device TID */


+ void *opbuf; /* Operation List buffer */

+ unsigned int oplen; /* Operation List buffer length in bytes */


+ void *resbuf; /* Result List buffer */

+ unsigned int *reslen; /* Result List buffer length in bytes */
+};
+
+struct i2o_sw_xfer
+{
+ unsigned int iop; /* IOP unit number */
+ unsigned char dl_flags; /* DownLoadFlags field */
+ unsigned char sw_type; /* Software type */
+ unsigned int sw_id; /* Software ID */


+ void *buf; /* Pointer to software buffer */

+ unsigned int *swlen; /* Length of software data */
+ unsigned int *maxfrag; /* Maximum fragment count */
+ unsigned int *curfrag; /* Current fragment count */
+};
+
+struct i2o_html
+{
+ unsigned int iop; /* IOP unit number */
+ unsigned int tid; /* Target device ID */
+ unsigned int page; /* HTML page */


+ void *resbuf; /* Buffer for reply HTML page */

+ unsigned int *reslen; /* Length in bytes of reply buffer */


+ void *qbuf; /* Pointer to HTTP query string */

+ unsigned int qlen; /* Length in bytes of query string buffer */
+};
+
+#endif
diff -u --recursive --new-file v2.3.5/linux/include/linux/igmp.h linux/include/linux/igmp.h
--- v2.3.5/linux/include/linux/igmp.h Mon Jan 12 15:28:18 1998
+++ linux/include/linux/igmp.h Wed Jun 9 14:45:36 1999
@@ -101,19 +101,7 @@
X char loaded;
X };
X
-extern __inline__ int ip_check_mc(struct device *dev, u32 mc_addr)
-{
- struct in_device *in_dev = dev->ip_ptr;
- struct ip_mc_list *im;
-
- if (in_dev) {
- for (im=in_dev->mc_list; im; im=im->next)
- if (im->multiaddr == mc_addr)
- return 1;
- }
- return 0;
-}
-
+extern int ip_check_mc(struct device *dev, u32 mc_addr);
X extern int igmp_rcv(struct sk_buff *, unsigned short);
X extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
X extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
diff -u --recursive --new-file v2.3.5/linux/include/linux/inet.h linux/include/linux/inet.h
--- v2.3.5/linux/include/linux/inet.h Thu May 15 16:48:05 1997
+++ linux/include/linux/inet.h Wed Jun 9 14:45:36 1999
@@ -46,6 +46,7 @@
X
X extern void inet_proto_init(struct net_proto *pro);
X extern char *in_ntoa(__u32 in);
+extern char *in_ntoa2(__u32 in, char *buf);
X extern __u32 in_aton(const char *str);
X
X #endif
diff -u --recursive --new-file v2.3.5/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.3.5/linux/include/linux/inetdevice.h Mon Jan 4 15:31:35 1999
+++ linux/include/linux/inetdevice.h Wed Jun 9 14:45:36 1999
@@ -74,7 +74,7 @@
X extern void devinet_init(void);
X extern struct in_device *inetdev_init(struct device *dev);
X extern struct in_device *inetdev_by_index(int);
-extern u32 inet_select_addr(struct device *dev, u32 dst, int scope);
+extern u32 inet_select_addr(const struct device *dev, u32 dst, int scope);
X extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
X extern void inet_forward_change(void);
X
diff -u --recursive --new-file v2.3.5/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.5/linux/include/linux/mm.h Fri May 14 18:55:29 1999
+++ linux/include/linux/mm.h Tue Jun 8 23:03:47 1999
@@ -314,6 +314,7 @@
X extern unsigned long do_mmap(struct file *, unsigned long, unsigned long,
X unsigned long, unsigned long, unsigned long);
X extern int do_munmap(unsigned long, size_t);
+extern unsigned long do_brk(unsigned long, unsigned long);
X
X /* filemap.c */
X extern void remove_inode_page(struct page *);
@@ -381,6 +382,8 @@
X vma = NULL;
X return vma;
X }
+
+extern struct vm_area_struct *find_extend_vma(struct task_struct *tsk, unsigned long addr);
X
X #define buffer_under_min() ((buffermem >> PAGE_SHIFT) * 100 < \
X buffer_mem.min_percent * num_physpages)
diff -u --recursive --new-file v2.3.5/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.5/linux/include/linux/netdevice.h Mon May 31 22:28:06 1999
+++ linux/include/linux/netdevice.h Wed Jun 9 14:45:36 1999
@@ -152,6 +152,7 @@
X struct hh_cache *hh_next; /* Next entry */
X atomic_t hh_refcnt; /* number of users */
X unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP */
+ int hh_len; /* length of header */
X int (*hh_output)(struct sk_buff *skb);
X rwlock_t hh_lock;
X /* cached hardware header; allow for machine alignment needs. */
@@ -260,6 +261,7 @@
X void *atalk_ptr; /* AppleTalk link */
X void *ip_ptr; /* IPv4 specific data */
X void *dn_ptr; /* DECnet specific data */
+ void *ip6_ptr; /* IPv6 specific data */
X
X struct Qdisc *qdisc;
X struct Qdisc *qdisc_sleeping;
@@ -268,6 +270,13 @@
X
X /* hard_start_xmit synchronizer */
X spinlock_t xmit_lock;
+ /* cpu id of processor entered to hard_start_xmit or -1,
+ if nobody entered there.
+ */
+ int xmit_lock_owner;
+ /* device queue lock */
+ spinlock_t queue_lock;
+ atomic_t refcnt;
X
X /* Pointers to interface service routines. */
X int (*open)(struct device *dev);
diff -u --recursive --new-file v2.3.5/linux/include/linux/nfs.h linux/include/linux/nfs.h
--- v2.3.5/linux/include/linux/nfs.h Sat Mar 6 14:21:13 1999
+++ linux/include/linux/nfs.h Tue Jun 8 22:11:58 1999
@@ -158,6 +158,11 @@
X const char * name;
X };
X
+struct nfs_readlinkargs {
+ struct nfs_fh * fh;
+ const void * buffer;
+};
+
X struct nfs_readargs {
X struct nfs_fh * fh;
X __u32 offset;
@@ -195,7 +200,7 @@
X struct nfs_fh * fh;
X __u32 cookie;
X void * buffer;
- unsigned int bufsiz;
+ int bufsiz;
X };
X
X struct nfs_diropok {
@@ -208,16 +213,10 @@
X unsigned int count;
X };
X
-struct nfs_readlinkres {
- char ** string;
- unsigned int * lenp;
- unsigned int maxlen;
- void * buffer;
-};
-
X struct nfs_readdirres {
X void * buffer;
- unsigned int bufsiz;
+ int bufsiz;
+ u32 cookie;
X };
X
X #endif /* NFS_NEED_XDR_TYPES */
diff -u --recursive --new-file v2.3.5/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.3.5/linux/include/linux/nfs_fs.h Wed Jun 2 14:44:39 1999
+++ linux/include/linux/nfs_fs.h Tue Jun 8 23:03:44 1999
@@ -79,6 +79,8 @@
X #define NFS_FLAGS(inode) ((inode)->u.nfs_i.flags)
X #define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATE)
X #define NFS_WRITEBACK(inode) ((inode)->u.nfs_i.writeback)
+#define NFS_COOKIES(inode) ((inode)->u.nfs_i.cookies)
+#define NFS_DIREOF(inode) ((inode)->u.nfs_i.direof)
X
X /*
X * These are the default flags for swap requests
@@ -139,9 +141,6 @@
X extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir,
X const char *name, struct nfs_fh *fhandle,
X struct nfs_fattr *fattr);
-extern int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
- void **p0, char **string, unsigned int *len,
- unsigned int maxlen);
X extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
X int swap, unsigned long offset, unsigned int count,
X void *buffer, struct nfs_fattr *fattr);
@@ -166,8 +165,6 @@
X struct nfs_fh *fhandle, struct nfs_fattr *fattr);
X extern int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir,
X const char *name);
-extern int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
- u32 cookie, unsigned int size, __u32 *entry);
X extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
X struct nfs_fsinfo *res);
X
@@ -195,9 +192,7 @@
X */
X extern struct inode_operations nfs_dir_inode_operations;
X extern struct dentry_operations nfs_dentry_operations;
-extern void nfs_free_dircache(void);
X extern void nfs_invalidate_dircache(struct inode *);
-extern void nfs_invalidate_dircache_sb(struct super_block *);
X
X /*
X * linux/fs/nfs/symlink.c
diff -u --recursive --new-file v2.3.5/linux/include/linux/nfs_fs_i.h linux/include/linux/nfs_fs_i.h
--- v2.3.5/linux/include/linux/nfs_fs_i.h Sat Mar 6 15:04:35 1999
+++ linux/include/linux/nfs_fs_i.h Tue Jun 8 22:42:23 1999
@@ -47,6 +47,10 @@
X * pages.
X */
X struct nfs_wreq * writeback;
+
+ /* Readdir caching information. */
+ void *cookies;
+ u32 direof;
X };
X
X /*
diff -u --recursive --new-file v2.3.5/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.3.5/linux/include/linux/pagemap.h Mon May 31 22:28:06 1999
+++ linux/include/linux/pagemap.h Tue Jun 8 23:03:47 1999
@@ -28,6 +28,7 @@
X #define PAGE_CACHE_SHIFT PAGE_SHIFT
X #define PAGE_CACHE_SIZE PAGE_SIZE
X #define PAGE_CACHE_MASK PAGE_MASK
+#define PAGE_CACHE_ALIGN(addr) (((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK)
X
X #define page_cache_alloc() __get_free_page(GFP_USER)
X #define page_cache_free(x) free_page(x)
diff -u --recursive --new-file v2.3.5/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.3.5/linux/include/linux/parport.h Mon May 31 22:28:06 1999
+++ linux/include/linux/parport.h Tue Jun 8 23:04:38 1999
@@ -103,9 +103,6 @@
X
X void (*change_mode)(struct parport *, int);
X
- void (*release_resources)(struct parport *);
- int (*claim_resources)(struct parport *);
-
X void (*epp_write_data)(struct parport *, unsigned char);
X unsigned char (*epp_read_data)(struct parport *);
X void (*epp_write_addr)(struct parport *, unsigned char);
@@ -169,6 +166,7 @@
X unsigned int waiting;
X struct pardevice *waitprev;
X struct pardevice *waitnext;
+ void * sysctl_table;
X };
X
X /* Directory information for the /proc interface */
@@ -210,6 +208,7 @@
X spinlock_t pardevice_lock;
X spinlock_t waitlist_lock;
X rwlock_t cad_lock;
+ void * sysctl_table;
X };
X
X struct parport_driver {
@@ -240,10 +239,6 @@
X /* parport_in_use returns nonzero if there are devices attached to a port. */
X #define parport_in_use(x) ((x)->devices != NULL)


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part21

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


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

X
-/* Put a parallel port to sleep; release its hardware resources. Only possible
- * if no devices are registered. */
-extern void parport_quiesce(struct parport *);
-
X /* parport_enumerate returns a pointer to the linked list of all the ports
X * in this machine.
X */
@@ -339,7 +334,7 @@
X #define PARPORT_DEV_LURK (1<<0) /* WARNING !! DEPRECATED !! */
X #define PARPORT_DEV_EXCL (1<<1) /* Need exclusive access. */
X
-#define PARPORT_FLAG_COMA (1<<0)
+#define PARPORT_FLAG_COMA_ (1<<0) /* No longer used. */
X #define PARPORT_FLAG_EXCL (1<<1) /* EXCL driver registered. */
X
X extern int parport_parse_irqs(int, const char *[], int irqval[]);
@@ -349,10 +344,12 @@
X char);
X
X /* Prototypes from parport_procfs */
-extern int parport_proc_init(void);
-extern void parport_proc_cleanup(void);
X extern int parport_proc_register(struct parport *pp);
X extern int parport_proc_unregister(struct parport *pp);
+extern int parport_device_proc_register(struct pardevice *device);
+extern int parport_device_proc_unregister(struct pardevice *device);
+extern int parport_default_proc_register(void);
+extern int parport_default_proc_unregister(void);
X
X extern void dec_parport_count(void);
X extern void inc_parport_count(void);
diff -u --recursive --new-file v2.3.5/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.5/linux/include/linux/pci.h Fri May 14 18:55:29 1999
+++ linux/include/linux/pci.h Wed Jun 9 16:59:16 1999
@@ -273,6 +273,8 @@
X #define PCI_CLASS_SERIAL_USB 0x0c03
X #define PCI_CLASS_SERIAL_FIBER 0x0c04
X
+#define PCI_CLASS_HOT_SWAP_CONTROLLER 0xff00
+
X #define PCI_CLASS_OTHERS 0xff
X
X /*
@@ -365,6 +367,7 @@
X #define PCI_DEVICE_ID_DEC_21150 0x0022
X #define PCI_DEVICE_ID_DEC_21152 0x0024
X #define PCI_DEVICE_ID_DEC_21153 0x0025
+#define PCI_DEVICE_ID_DEC_21154 0x0026
X
X #define PCI_VENDOR_ID_CIRRUS 0x1013
X #define PCI_DEVICE_ID_CIRRUS_7548 0x0038
@@ -510,9 +513,12 @@
X #define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
X
X #define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507
X #define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001
X #define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
X #define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
+#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802
+#define PCI_DEVICE_ID_MOTOROLA_CPX8216 0x4806
X
X #define PCI_VENDOR_ID_PROMISE 0x105a
X #define PCI_DEVICE_ID_PROMISE_20246 0x4d33
@@ -1062,9 +1068,11 @@
X
X #define PCI_VENDOR_ID_ADAPTEC 0x9004
X #define PCI_DEVICE_ID_ADAPTEC_7810 0x1078
+#define PCI_DEVICE_ID_ADAPTEC_7821 0x2178
X #define PCI_DEVICE_ID_ADAPTEC_7850 0x5078
X #define PCI_DEVICE_ID_ADAPTEC_7855 0x5578
X #define PCI_DEVICE_ID_ADAPTEC_5800 0x5800
+#define PCI_DEVICE_ID_ADAPTEC_3860 0x6038
X #define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
X #define PCI_DEVICE_ID_ADAPTEC_7860 0x6078
X #define PCI_DEVICE_ID_ADAPTEC_7861 0x6178
@@ -1079,15 +1087,28 @@
X #define PCI_DEVICE_ID_ADAPTEC_7882 0x8278
X #define PCI_DEVICE_ID_ADAPTEC_7883 0x8378
X #define PCI_DEVICE_ID_ADAPTEC_7884 0x8478
+#define PCI_DEVICE_ID_ADAPTEC_7885 0x8578
+#define PCI_DEVICE_ID_ADAPTEC_7886 0x8678
+#define PCI_DEVICE_ID_ADAPTEC_7887 0x8778
+#define PCI_DEVICE_ID_ADAPTEC_7888 0x8878
X #define PCI_DEVICE_ID_ADAPTEC_1030 0x8b78
X
X #define PCI_VENDOR_ID_ADAPTEC2 0x9005
X #define PCI_DEVICE_ID_ADAPTEC2_2940U2 0x0010
-#define PCI_DEVICE_ID_ADAPTEC2_78902 0x0013
+#define PCI_DEVICE_ID_ADAPTEC2_2930U2 0x0011
+#define PCI_DEVICE_ID_ADAPTEC2_7890B 0x0013
X #define PCI_DEVICE_ID_ADAPTEC2_7890 0x001f
X #define PCI_DEVICE_ID_ADAPTEC2_3940U2 0x0050
X #define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051
X #define PCI_DEVICE_ID_ADAPTEC2_7896 0x005f
+#define PCI_DEVICE_ID_ADAPTEC2_7892A 0x0080
+#define PCI_DEVICE_ID_ADAPTEC2_7892B 0x0081
+#define PCI_DEVICE_ID_ADAPTEC2_7892D 0x0083
+#define PCI_DEVICE_ID_ADAPTEC2_7892P 0x008f
+#define PCI_DEVICE_ID_ADAPTEC2_7899A 0x00c0
+#define PCI_DEVICE_ID_ADAPTEC2_7899B 0x00c1
+#define PCI_DEVICE_ID_ADAPTEC2_7899D 0x00c3
+#define PCI_DEVICE_ID_ADAPTEC2_7899P 0x00cf
X
X #define PCI_VENDOR_ID_ATRONICS 0x907f
X #define PCI_DEVICE_ID_ATRONICS_2015 0x2015
diff -u --recursive --new-file v2.3.5/linux/include/linux/pkt_sched.h linux/include/linux/pkt_sched.h
--- v2.3.5/linux/include/linux/pkt_sched.h Tue Apr 28 11:10:10 1998
+++ linux/include/linux/pkt_sched.h Wed Jun 9 14:45:36 1999
@@ -38,6 +38,9 @@
X __u32 pps; /* Current flow packet rate */
X __u32 qlen;
X __u32 backlog;
+#ifdef __KERNEL__
+ spinlock_t *lock;
+#endif
X };
X
X struct tc_estimator
diff -u --recursive --new-file v2.3.5/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.5/linux/include/linux/proc_fs.h Mon May 31 22:28:06 1999
+++ linux/include/linux/proc_fs.h Tue Jun 8 23:04:14 1999
@@ -52,7 +52,8 @@
X PROC_STRAM,
X PROC_SOUND,
X PROC_MTRR, /* whether enabled or not */
- PROC_FS
+ PROC_FS,
+ PROC_SYSVIPC
X };
X
X enum pid_directory_inos {
@@ -207,6 +208,7 @@
X PROC_SCSI_INIA100,
X PROC_SCSI_FCAL,
X PROC_SCSI_I2O,
+ PROC_SCSI_USB_SCSI,
X PROC_SCSI_SCSI_DEBUG,
X PROC_SCSI_NOT_PRESENT,
X PROC_SCSI_FILE, /* I'm assuming here that we */
@@ -243,6 +245,12 @@
X PROC_CODA_FS_LAST
X };
X
+enum sysvipc_directory_inos {
+ PROC_SYSVIPC_SHM = PROC_CODA_FS_LAST,
+ PROC_SYSVIPC_SEM,
+ PROC_SYSVIPC_MSG
+};
+
X /* Finally, the dynamically allocatable proc entries are reserved: */
X
X #define PROC_DYNAMIC_FIRST 4096
@@ -313,6 +321,7 @@
X extern struct proc_dir_entry proc_pid_fd;
X extern struct proc_dir_entry proc_mca;
X extern struct proc_dir_entry *proc_bus;
+extern struct proc_dir_entry *proc_sysvipc;
X
X extern struct inode_operations proc_scsi_inode_operations;
X
@@ -422,6 +431,7 @@
X #endif
X extern struct inode_operations proc_omirr_inode_operations;
X extern struct inode_operations proc_ppc_htab_inode_operations;
+extern struct inode_operations proc_sysvipc_inode_operations;
X
X /*
X * generic.c
diff -u --recursive --new-file v2.3.5/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
--- v2.3.5/linux/include/linux/rtnetlink.h Mon May 31 22:28:06 1999
+++ linux/include/linux/rtnetlink.h Wed Jun 9 14:45:36 1999
@@ -515,9 +515,6 @@
X
X #ifdef __KERNEL__
X
-extern atomic_t rtnl_rlockct;
-extern wait_queue_head_t rtnl_wait;
-
X extern __inline__ int rtattr_strcmp(struct rtattr *rta, char *str)
X {
X int len = strlen(str) + 1;
@@ -544,127 +541,31 @@
X #define RTA_PUT(skb, attrtype, attrlen, data) \
X ({ if (skb_tailroom(skb) < (int)RTA_SPACE(attrlen)) goto rtattr_failure; \
X __rta_fill(skb, attrtype, attrlen, data); })
-
-extern unsigned long rtnl_wlockct;
-
-/* NOTE: these locks are not interrupt safe, are not SMP safe,
- * they are even not atomic. 8)8)8) ... and it is not a bug.
- * Really, if these locks will be programmed correctly,
- * all the addressing/routing machine would become SMP safe,
- * but is absolutely useless at the moment, because all the kernel
- * is not reenterable in any case. --ANK
- *
- * Well, atomic_* and set_bit provide the only thing here:
- * gcc is confused not to overoptimize them, that's all.
- * I remember as gcc splitted ++ operation, but cannot reproduce
- * it with gcc-2.7.*. --ANK
- *
- * One more note: rwlock facility should be written and put
- * to a kernel wide location: f.e. current implementation of semaphores
- * (especially, for x86) looks like a wonder. It would be good
- * to have something similar for rwlock. Recursive lock could be also
- * useful thing. --ANK
- */
-
-extern __inline__ int rtnl_shlock_nowait(void)
-{
- atomic_inc(&rtnl_rlockct);
- if (test_bit(0, &rtnl_wlockct)) {
- atomic_dec(&rtnl_rlockct);
- return -EAGAIN;


- }
- return 0;
-}
-

-extern __inline__ void rtnl_shlock(void)
-{
- while (rtnl_shlock_nowait())
- sleep_on(&rtnl_wait);
-}
-
-/* Check for possibility to PROMOTE shared lock to exclusive.
- Shared lock must be already grabbed with rtnl_shlock*().
- */
-
-extern __inline__ int rtnl_exlock_nowait(void)
-{
- if (atomic_read(&rtnl_rlockct) > 1)
- return -EAGAIN;
- if (test_and_set_bit(0, &rtnl_wlockct))
- return -EAGAIN;


- return 0;
-}
-

-extern __inline__ void rtnl_exlock(void)
-{
- while (rtnl_exlock_nowait())
- sleep_on(&rtnl_wait);
-}
-
-#if 0
-extern __inline__ void rtnl_shunlock(void)
-{
- atomic_dec(&rtnl_rlockct);
- if (atomic_read(&rtnl_rlockct) <= 1) {
- wake_up(&rtnl_wait);
- if (rtnl && rtnl->receive_queue.qlen)
- rtnl->data_ready(rtnl, 0);
- }
-}
-#else
-
-/* The problem: inline requires to include <net/sock.h> and, hence,
- almost all of net includes :-(
- */
-
-#define rtnl_shunlock() ({ \
- atomic_dec(&rtnl_rlockct); \
- if (atomic_read(&rtnl_rlockct) <= 1) { \
- wake_up(&rtnl_wait); \
- if (rtnl && rtnl->receive_queue.qlen) \
- rtnl->data_ready(rtnl, 0); \
- } \
-})
X #endif
X
-/* Release exclusive lock. Note, that we do not wake up rtnetlink socket,
- * it will be done later after releasing shared lock.
- */
-
-extern __inline__ void rtnl_exunlock(void)
-{
- clear_bit(0, &rtnl_wlockct);
- wake_up(&rtnl_wait);
-}
-
-#else
+extern struct semaphore rtnl_sem;
X
-extern __inline__ void rtnl_shlock(void)
-{
- while (atomic_read(&rtnl_rlockct))
- sleep_on(&rtnl_wait);
- atomic_inc(&rtnl_rlockct);
-}
+#define rtnl_exlock() do { } while(0)
+#define rtnl_exunlock() do { } while(0)
+#define rtnl_exlock_nowait() (0)
X
-extern __inline__ void rtnl_shunlock(void)
-{
- if (atomic_dec_and_test(&rtnl_rlockct))
- wake_up(&rtnl_wait);
-}
-
-extern __inline__ void rtnl_exlock(void)
-{
-}
-
-extern __inline__ void rtnl_exunlock(void)
-{
-}
+#define rtnl_shlock() down(&rtnl_sem)
+#define rtnl_shlock_nowait() down_trylock(&rtnl_sem)
X
+#ifndef CONFIG_RTNETLINK
+#define rtnl_shunlock() up(&rtnl_sem)
+#else
+#define rtnl_shunlock() do { up(&rtnl_sem); \
+ if (rtnl && rtnl->receive_queue.qlen) \
+ rtnl->data_ready(rtnl, 0); \
+ } while(0)
X #endif
X
X extern void rtnl_lock(void);
X extern void rtnl_unlock(void);
X extern void rtnetlink_init(void);
+
+


X
X #endif /* __KERNEL__ */
X

diff -u --recursive --new-file v2.3.5/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.5/linux/include/linux/sched.h Mon May 31 22:28:06 1999
+++ linux/include/linux/sched.h Tue Jun 8 23:03:44 1999
@@ -163,9 +163,9 @@
X #define AVL_MIN_MAP_COUNT 32
X
X struct mm_struct {
- struct vm_area_struct *mmap; /* list of VMAs */
- struct vm_area_struct *mmap_avl; /* tree of VMAs */
- struct vm_area_struct *mmap_cache; /* last find_vma result */
+ struct vm_area_struct * mmap; /* list of VMAs */
+ struct vm_area_struct * mmap_avl; /* tree of VMAs */
+ struct vm_area_struct * mmap_cache; /* last find_vma result */
X pgd_t * pgd;
X atomic_t count;
X int map_count; /* number of VMAs */
@@ -453,8 +453,8 @@
X }
X
X /* per-UID process charging. */
-extern int alloc_uid(struct task_struct *p);
-void free_uid(struct task_struct *p);
+extern int alloc_uid(struct task_struct *);
+void free_uid(struct task_struct *);
X
X #include <asm/current.h>
X
@@ -482,26 +482,25 @@
X #define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
X #define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE)
X
-extern int in_group_p(gid_t grp);
+extern int in_group_p(gid_t);
X
X extern void flush_signals(struct task_struct *);
X extern void flush_signal_handlers(struct task_struct *);
-extern int dequeue_signal(sigset_t *block, siginfo_t *);
-extern int send_sig_info(int, struct siginfo *info, struct task_struct *);
-extern int force_sig_info(int, struct siginfo *info, struct task_struct *);
-extern int kill_pg_info(int, struct siginfo *info, pid_t);
-extern int kill_sl_info(int, struct siginfo *info, pid_t);
-extern int kill_proc_info(int, struct siginfo *info, pid_t);
-extern int kill_something_info(int, struct siginfo *info, int);
-extern void notify_parent(struct task_struct * tsk, int);
-extern void force_sig(int sig, struct task_struct * p);
-extern int send_sig(int sig, struct task_struct * p, int priv);
+extern int dequeue_signal(sigset_t *, siginfo_t *);
+extern int send_sig_info(int, struct siginfo *, struct task_struct *);
+extern int force_sig_info(int, struct siginfo *, struct task_struct *);
+extern int kill_pg_info(int, struct siginfo *, pid_t);
+extern int kill_sl_info(int, struct siginfo *, pid_t);
+extern int kill_proc_info(int, struct siginfo *, pid_t);
+extern int kill_something_info(int, struct siginfo *, int);
+extern void notify_parent(struct task_struct *, int);
+extern void force_sig(int, struct task_struct *);
+extern int send_sig(int, struct task_struct *, int);
X extern int kill_pg(pid_t, int, int);
X extern int kill_sl(pid_t, int, int);
X extern int kill_proc(pid_t, int, int);
-extern int do_sigaction(int sig, const struct k_sigaction *act,
- struct k_sigaction *oact);
-extern int do_sigaltstack(const stack_t *ss, stack_t *oss, unsigned long sp);
+extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *);
+extern int do_sigaltstack(const stack_t *, stack_t *, unsigned long);
X
X extern inline int signal_pending(struct task_struct *p)
X {
@@ -552,12 +551,10 @@
X : on_sig_stack(sp) ? SS_ONSTACK : 0);
X }
X
-extern int request_irq(unsigned int irq,
+extern int request_irq(unsigned int,
X void (*handler)(int, void *, struct pt_regs *),
- unsigned long flags,
- const char *device,
- void *dev_id);
-extern void free_irq(unsigned int irq, void *dev_id);
+ unsigned long, const char *, void *);
+extern void free_irq(unsigned int, void *);
X
X /*
X * This has now become a routine instead of a macro, it sets a flag if
diff -u --recursive --new-file v2.3.5/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.5/linux/include/linux/sysctl.h Mon May 31 22:28:06 1999
+++ linux/include/linux/sysctl.h Thu Jun 3 16:21:47 1999
@@ -452,12 +452,42 @@
X /* CTL_DEV names: */
X enum {
X DEV_CDROM=1,
- DEV_HWMON=2
+ DEV_HWMON=2,
+ DEV_PARPORT=3
X };
X
X /* /proc/sys/dev/cdrom */
X enum {
X DEV_CDROM_INFO=1
+};
+
+/* /proc/sys/dev/parport */
+enum {
+ DEV_PARPORT_DEFAULT=-3
+};
+
+/* /proc/sys/dev/parport/default */
+enum {
+ DEV_PARPORT_DEFAULT_TIMESLICE=1,
+ DEV_PARPORT_DEFAULT_SPINTIME=2
+};
+
+/* /proc/sys/dev/parport/parport n */
+enum {
+ DEV_PARPORT_SPINTIME=1,
+ DEV_PARPORT_HARDWARE=2,
+ DEV_PARPORT_DEVICES=3,
+ DEV_PARPORT_AUTOPROBE=16
+};
+
+/* /proc/sys/dev/parport/parport n/devices/ */
+enum {
+ DEV_PARPORT_DEVICES_ACTIVE=-3,
+};
+
+/* /proc/sys/dev/parport/parport n/devices/device n */
+enum {
+ DEV_PARPORT_DEVICE_TIMESLICE=1,
X };
X
X #ifdef __KERNEL__
diff -u --recursive --new-file v2.3.5/linux/include/linux/wanrouter.h linux/include/linux/wanrouter.h
--- v2.3.5/linux/include/linux/wanrouter.h Tue May 11 13:06:00 1999
+++ linux/include/linux/wanrouter.h Tue Jun 8 23:05:38 1999
@@ -5,6 +5,7 @@
X *
X * Author: Gene Kozin <ge...@compuserve.com>
X * Jaspreet Singh <jasp...@sangoma.com>
+* Additions: Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
X *
X * Copyright: (c) 1995-1997 Sangoma Technologies Inc.
X *
@@ -13,11 +14,14 @@


X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X * ============================================================================

+* May 23, 1999 Arnaldo Melo Added local_addr to wanif_conf_t
+* WAN_DISCONNECTING state added
X * Nov 06, 1997 Jaspreet Singh Changed Router Driver version to 1.1 from 1.0
X * Oct 20, 1997 Jaspreet Singh Added 'cir','bc','be' and 'mc' to 'wanif_conf_t'
X * Added 'enable_IPX' and 'network_number' to
X * 'wan_device_t'. Also added defines for
-* UDP PACKET TYPE, Interrupt test, critical values* for RACE conditions.
+* UDP PACKET TYPE, Interrupt test, critical values
+* for RACE conditions.
X * Oct 05, 1997 Jaspreet Singh Added 'dlci_num' and 'dlci[100]' to
X * 'wan_fr_conf_t' to configure a list of dlci(s)
X * for a NODE
@@ -125,7 +129,7 @@
X unsigned n392; /* error threshold counter */
X unsigned n393; /* monitored events counter */
X unsigned dlci_num; /* number of DLCs (access node) */
- unsigned dlci[100]; /* List of all DLCIs */
+ unsigned dlci[100]; /* List of all DLCIs */
X } wan_fr_conf_t;
X
X /*----------------------------------------------------------------------------
@@ -274,6 +278,7 @@
X WAN_DISCONNECTED, /* link/channel is disconnected */
X WAN_CONNECTING, /* connection is in progress */
X WAN_CONNECTED, /* link/channel is operational */
+ WAN_DISCONNECTING, /* disconnection is in progress */
X WAN_LIMIT /* for verification only */
X };
X
@@ -298,6 +303,8 @@
X unsigned bc; /* Committed Burst Size fwd, bwd */
X unsigned be; /* Excess Burst Size fwd, bwd */
X char mc; /* Multicast on or off */
+ char local_addr[WAN_ADDRESS_SZ+1];/* local media address, ASCIIZ */
+ unsigned char port; /* board port */
X int reserved[8]; /* reserved for future extensions */
X } wanif_conf_t;
X
diff -u --recursive --new-file v2.3.5/linux/include/net/addrconf.h linux/include/net/addrconf.h
--- v2.3.5/linux/include/net/addrconf.h Sun Mar 21 07:22:00 1999
+++ linux/include/net/addrconf.h Wed Jun 9 14:45:36 1999
@@ -56,7 +56,7 @@
X extern int ipv6_get_saddr(struct dst_entry *dst,
X struct in6_addr *daddr,
X struct in6_addr *saddr);
-extern struct inet6_ifaddr * ipv6_get_lladdr(struct device *dev);
+extern int ipv6_get_lladdr(struct device *dev, struct in6_addr *);
X
X /*
X * multicast prototypes (mcast.c)
@@ -68,6 +68,7 @@
X int ifindex,
X struct in6_addr *addr);
X extern void ipv6_sock_mc_close(struct sock *sk);
+extern int inet6_mc_check(struct sock *sk, struct in6_addr *addr);
X
X extern int ipv6_dev_mc_inc(struct device *dev,
X struct in6_addr *addr);
diff -u --recursive --new-file v2.3.5/linux/include/net/dst.h linux/include/net/dst.h
--- v2.3.5/linux/include/net/dst.h Mon May 31 22:28:06 1999
+++ linux/include/net/dst.h Wed Jun 9 14:45:36 1999
@@ -170,6 +170,9 @@
X if (dst->expires == 0 || (long)(dst->expires - expires) > 0)
X dst->expires = expires;
X }
+
+extern void dst_init(void);
+
X #endif
X
X #endif /* _NET_DST_H */
diff -u --recursive --new-file v2.3.5/linux/include/net/if_inet6.h linux/include/net/if_inet6.h
--- v2.3.5/linux/include/net/if_inet6.h Sun Mar 1 14:40:40 1998
+++ linux/include/net/if_inet6.h Wed Jun 9 14:45:36 1999
@@ -44,6 +44,7 @@
X __u32 valid_lft;
X __u32 prefered_lft;
X unsigned long tstamp;
+ atomic_t refcnt;
X
X __u8 probes;
X __u8 flags;


@@ -108,6 +109,7 @@
X

X struct inet6_ifaddr *addr_list;
X struct ifmcaddr6 *mc_list;
+ rwlock_t lock;
X __u32 if_flags;
X
X struct neigh_parms *nd_parms;
diff -u --recursive --new-file v2.3.5/linux/include/net/ip.h linux/include/net/ip.h
--- v2.3.5/linux/include/net/ip.h Mon May 31 22:28:06 1999
+++ linux/include/net/ip.h Wed Jun 9 14:45:36 1999
@@ -146,10 +146,10 @@
X skb->protocol = __constant_htons(ETH_P_IP);
X
X if (hh) {
- read_lock_irq(&hh->hh_lock);
+ read_lock_bh(&hh->hh_lock);
X memcpy(skb->data - 16, hh->hh_data, 16);
- read_unlock_irq(&hh->hh_lock);
- skb_push(skb, dev->hard_header_len);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
X return hh->hh_output(skb);
X } else if (dst->neighbour)
X return dst->neighbour->output(skb);
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h
--- v2.3.5/linux/include/net/irda/dongle.h Mon May 31 22:28:07 1999
+++ linux/include/net/irda/dongle.h Mon Jun 7 16:18:58 1999


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

X * Created at: Wed Oct 21 22:47:12 1998
- * Modified at: Mon May 10 14:51:06 1999
+ * Modified at: Sun May 16 13:40:03 1999


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

X *

X * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.

@@ -35,15 +35,15 @@
X ACTISYS_PLUS_DONGLE,
X GIRBIL_DONGLE,
X LITELINK_DONGLE,
-} DONGLE_T;
+} IRDA_DONGLE;
X
X struct irda_device;
X
X struct dongle {
- DONGLE_T type;
+ IRDA_DONGLE type;
X void (*open)(struct irda_device *, int type);
X void (*close)(struct irda_device *);
- void (*reset)( struct irda_device *, int unused);
+ void (*reset)( struct irda_device *);
X void (*change_speed)( struct irda_device *, int baudrate);
X void (*qos_init)( struct irda_device *, struct qos_info *);
X };
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h
--- v2.3.5/linux/include/net/irda/ircomm_common.h Mon May 31 22:28:07 1999
+++ linux/include/net/irda/ircomm_common.h Mon Jun 7 16:18:58 1999
@@ -77,9 +77,9 @@
X
X #define IRCOMM_MAGIC 0x434f4d4d
X #define COMM_INIT_CTRL_PARAM 3 /* length of initial control parameters */
-#define COMM_HEADER 1 /* length of clen field */
-#define COMM_HEADER_SIZE (TTP_MAX_HEADER+COMM_HEADER)
-#define COMM_DEFAULT_DATA_SIZE 64
+#define COMM_HEADER_SIZE 1 /* length of clen field */
+#define COMM_MAX_HEADER_SIZE (TTP_MAX_HEADER+COMM_HEADER_SIZE)
+#define COMM_DEFAULT_SDU_SIZE (64 - COMM_HEADER_SIZE)
X #define IRCOMM_MAX_CONNECTION 1 /* Don't change for now */
X
X
@@ -177,8 +177,8 @@
X int null_modem_mode; /* switch for null modem emulation */
X int ttp_stop;
X
- int max_txbuff_size;
- __u32 max_sdu_size;
+ __u32 tx_max_sdu_size;
+ __u32 rx_max_sdu_size;
X __u8 max_header_size;
X
X __u32 daddr; /* Device address of the peer device */
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.3.5/linux/include/net/irda/irda_device.h Mon May 31 22:28:07 1999
+++ linux/include/net/irda/irda_device.h Mon Jun 7 16:18:58 1999


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

X * Created at: Tue Apr 14 12:41:42 1998
- * Modified at: Mon May 10 15:46:02 1999
+ * Modified at: Wed May 19 08:44:48 1999


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

X *

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

@@ -124,14 +124,14 @@
X
X struct dongle *dongle; /* Dongle driver */
X
- /* spinlock_t lock; */ /* For serializing operations */
+ spinlock_t lock; /* For serializing operations */
X
X /* Media busy stuff */
X int media_busy;
X struct timer_list media_busy_timer;
X
X /* Callbacks for driver specific implementation */
- void (*change_speed)(struct irda_device *driver, int baud);
+ void (*change_speed)(struct irda_device *idev, int baud);
X int (*is_receiving)(struct irda_device *); /* receiving? */
X void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts);
X int (*raw_write)(struct irda_device *idev, __u8 *buf, int len);
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h
--- v2.3.5/linux/include/net/irda/irlan_common.h Mon May 31 22:28:07 1999
+++ linux/include/net/irda/irlan_common.h Mon Jun 7 16:18:58 1999


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

X * Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Sun May 9 11:45:33 1999
+ * Modified at: Mon May 31 13:54:20 1999


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

X *
X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>,
@@ -124,6 +124,9 @@
X int unicast_open;
X int broadcast_open;
X
+ int tx_busy;
+ struct sk_buff_head txq; /* Transmit control queue */
+
X struct timer_list kick_timer;
X };
X
@@ -163,7 +166,7 @@
X struct device dev; /* Ethernet device structure*/
X struct enet_statistics stats;
X
- __u32 saddr; /* Source devcie address */
+ __u32 saddr; /* Source device address */
X __u32 daddr; /* Destination device address */
X int netdev_registered;
X int notify_irmanager;
@@ -200,6 +203,8 @@
X void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout);
X
X void irlan_open_data_tsap(struct irlan_cb *self);
+
+int irlan_run_ctrl_tx_queue(struct irlan_cb *self);
X
X void irlan_get_provider_info(struct irlan_cb *self);
X void irlan_get_unicast_addr(struct irlan_cb *self);
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/irlan_eth.h linux/include/net/irda/irlan_eth.h
--- v2.3.5/linux/include/net/irda/irlan_eth.h Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/irlan_eth.h Mon Jun 7 16:18:58 1999
@@ -6,10 +6,10 @@


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

X * Created at: Thu Oct 15 08:36:58 1998
- * Modified at: Thu Apr 22 14:09:37 1999
+ * Modified at: Fri May 14 23:29:00 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
@@ -32,6 +32,7 @@
X int irlan_eth_xmit(struct sk_buff *skb, struct device *dev);
X
X void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
+void irlan_eth_send_gratuitous_arp(struct device *dev);
X
X void irlan_eth_set_multicast_list( struct device *dev);
X struct enet_statistics *irlan_eth_get_stats(struct device *dev);
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.5/linux/include/net/irda/irport.h Mon May 31 22:28:07 1999
+++ linux/include/net/irda/irport.h Mon Jun 7 16:18:58 1999


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

X * Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Mon May 10 22:12:56 1999
+ * Modified at: Wed May 19 15:31:16 1999


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

X *
X * Copyright (c) 1997, 1998-1999 Dag Brattli <da...@cs.uit.no>
@@ -49,13 +49,14 @@
X
X #define FRAME_MAX_SIZE 2048
X
-void irport_start(int iobase);
-void irport_stop(int iobase);
+void irport_start(struct irda_device *idev, int iobase);
+void irport_stop(struct irda_device *idev, int iobase);
X int irport_probe(int iobase);
X
X void irport_change_speed(struct irda_device *idev, int speed);
X void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
X
X int irport_hard_xmit(struct sk_buff *skb, struct device *dev);
+void irport_wait_until_sent(struct irda_device *idev);
X
X #endif
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/irqueue.h linux/include/net/irda/irqueue.h
--- v2.3.5/linux/include/net/irda/irqueue.h Tue May 11 13:04:00 1999
+++ linux/include/net/irda/irqueue.h Tue Jun 8 23:03:42 1999


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

X * Created at: Tue Jun 9 13:26:50 1998
- * Modified at: Thu Feb 25 20:34:21 1999
+ * Modified at: Tue May 25 07:54:41 1999


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

X *
X * Copyright (C) 1998, Aage Kvalnes <aa...@cs.uit.no>


@@ -29,8 +29,6 @@
X

X #include <linux/types.h>
X #include <asm/spinlock.h>
-
-/* #include <net/irda/irda.h> */
X
X #ifndef QUEUE_H
X #define QUEUE_H
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/irvtd.h linux/include/net/irda/irvtd.h
--- v2.3.5/linux/include/net/irda/irvtd.h Fri May 14 18:55:30 1999
+++ linux/include/net/irda/irvtd.h Mon Jun 7 16:18:58 1999
@@ -53,6 +53,8 @@
X struct sk_buff_head rxbuff;
X struct ircomm_cb *comm; /* ircomm instance */
X
+ __u32 tx_max_sdu_size;
+ __u32 max_header_size;
X /*
X * These members are used for compatibility with usual serial device.
X * See linux/serial.h
@@ -69,7 +71,8 @@
X wait_queue_head_t delta_msr_wait;
X wait_queue_head_t tx_wait;
X
- struct timer_list timer;
+ struct timer_list tx_timer;
+ struct timer_list rx_timer;
X
X long pgrp;
X long session;
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/smc-ircc.h linux/include/net/irda/smc-ircc.h
--- v2.3.5/linux/include/net/irda/smc-ircc.h Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/smc-ircc.h Mon Jun 7 16:18:58 1999
@@ -0,0 +1,160 @@
+/*********************************************************************
+ *
+ * Filename: smc.h
+ * Version:
+ * Description:

+ * Status: Experimental.
+ * Author: Thomas Davis (tad...@jps.net)
+ *

+ * Copyright (c) 1998, 1999 Thomas Davis (tad...@jps.net>
+ * All Rights Reserved


+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * I, Thomas Davis, admit no liability nor provide warranty for any
+ * of this software. This material is provided "AS-IS" and at no charge.
+ *

+ * Definitions for the SMC IrCC controller.


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

+#ifndef SMC_IRCC_H
+#define SMC_IRCC_H
+
+#define UART_MASTER 0x07
+#define UART_MASTER_POWERDOWN 1<<7
+#define UART_MASTER_RESET 1<<6
+#define UART_MASTER_INT_EN 1<<5
+#define UART_MASTER_ERROR_RESET 1<<4
+
+/* Register block 0 */
+
+#define UART_IIR 0x01
+#define UART_IER 0x02
+#define UART_LSR 0x03
+#define UART_LCR_A 0x04
+#define UART_LCR_B 0x05
+#define UART_BSR 0x06
+
+#define UART_IIR_ACTIVE_FRAME 1<<7
+#define UART_IIR_EOM 1<<6
+#define UART_IIR_RAW_MODE 1<<5
+#define UART_IIR_FIFO 1<<4
+
+#define UART_IER_ACTIVE_FRAME 1<<7
+#define UART_IER_EOM 1<<6
+#define UART_IER_RAW_MODE 1<<5
+#define UART_IER_FIFO 1<<4
+
+#define UART_LSR_UNDERRUN 1<<7
+#define UART_LSR_OVERRUN 1<<6
+#define UART_LSR_FRAME_ERROR 1<<5
+#define UART_LSR_SIZE_ERROR 1<<4
+#define UART_LSR_CRC_ERROR 1<<3
+#define UART_LSR_FRAME_ABORT 1<<2
+
+#define UART_LCR_A_FIFO_RESET 1<<7
+#define UART_LCR_A_FAST 1<<6
+#define UART_LCR_A_GP_DATA 1<<5
+#define UART_LCR_A_RAW_TX 1<<4
+#define UART_LCR_A_RAW_RX 1<<3
+#define UART_LCR_A_ABORT 1<<2
+#define UART_LCR_A_DATA_DONE 1<<1
+
+#define UART_LCR_B_SCE_DISABLED 0x00<<6
+#define UART_LCR_B_SCE_TRANSMIT 0x01<<6
+#define UART_LCR_B_SCE_RECEIVE 0x02<<6
+#define UART_LCR_B_SCE_UNDEFINED 0x03<<6
+#define UART_LCR_B_SIP_ENABLE 1<<5
+#define UART_LCR_B_BRICK_WALL 1<<4
+
+#define UART_BSR_NOT_EMPTY 1<<7
+#define UART_BSR_FIFO_FULL 1<<6
+#define UART_BSR_TIMEOUT 1<<5
+
+/* Register block 1 */
+
+#define UART_SCE_CFGA 0x00
+#define UART_SCE_CFGB 0x01
+#define UART_FIFO_THRESHOLD 0x02
+
+#define UART_CFGA_AUX_IR 0x01<<7
+#define UART_CFGA_HALF_DUPLEX 0x01<<2
+#define UART_CFGA_TX_POLARITY 0x01<<1
+#define UART_CFGA_RX_POLARITY 0x01
+
+#define UART_CFGA_COM 0x00<<3
+#define UART_CFGA_IRDA_SIR_A 0x01<<3
+#define UART_CFGA_ASK_SIR 0x02<<3
+#define UART_CFGA_IRDA_SIR_B 0x03<<3
+#define UART_CFGA_IRDA_HDLC 0x04<<3
+#define UART_CFGA_IRDA_4PPM 0x05<<3
+#define UART_CFGA_CONSUMER 0x06<<3
+#define UART_CFGA_RAW_IR 0x07<<3
+#define UART_CFGA_OTHER 0x08<<3
+
+#define UART_IR_HDLC 0x04
+#define UART_IR_4PPM 0x01
+#define UART_IR_CONSUMER 0x02
+
+#define UART_CFGB_LOOPBACK 0x01<<5
+#define UART_CFGB_LPBCK_TX_CRC 0x01<<4
+#define UART_CFGB_NOWAIT 0x01<<3
+#define UART_CFGB_STRING_MOVE 0x01<<2
+#define UART_CFGB_DMA_BURST 0x01<<1
+#define UART_CFGB_DMA_ENABLE 0x01
+
+#define UART_CFGB_COM 0x00<<6
+#define UART_CFGB_IR 0x01<<6
+#define UART_CFGB_AUX 0x02<<6
+#define UART_CFGB_INACTIVE 0x03<<6
+
+/* Register block 2 - Consumer IR - not used */
+
+/* Register block 3 - Identification Registers! */
+
+#define UART_ID_HIGH 0x00 /* 0x10 */
+#define UART_ID_LOW 0x01 /* 0xB8 */
+#define UART_CHIP_ID 0x02 /* 0xF1 */
+#define UART_VERSION 0x03 /* 0x01 */
+#define UART_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
+
+/* Register block 4 - IrDA */
+#define UART_CONTROL 0x00
+#define UART_BOF_COUNT_LO 0x01
+#define UART_BRICKWALL_CNT_LO 0x02
+#define UART_BRICKWALL_TX_CNT_HI 0x03
+#define UART_TX_SIZE_LO 0x04
+#define UART_RX_SIZE_HI 0x05
+#define UART_RX_SIZE_LO 0x06
+
+#define UART_1152 0x01<<7
+#define UART_CRC 0x01<<6
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+ int status;
+ int len;
+};
+
+struct st_fifo {
+ struct st_fifo_entry entries[10];
+ int head;
+ int tail;
+ int len;
+};
+
+/* Private data for each instance */
+struct ircc_cb {
+ struct st_fifo st_fifo;
+
+ int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
+ int tx_len; /* Number of frames in tx_buff */
+
+ struct irda_device idev;
+};
+
+#endif
diff -u --recursive --new-file v2.3.5/linux/include/net/irda/smc_ircc.h linux/include/net/irda/smc_ircc.h
--- v2.3.5/linux/include/net/irda/smc_ircc.h Thu Dec 17 09:01:03 1998
+++ linux/include/net/irda/smc_ircc.h Wed Dec 31 16:00:00 1969
@@ -1,123 +0,0 @@
-#if 0
-static char *rcsid = "$Id: smc_ircc.h,v 1.5 1998/07/27 01:25:29 ratbert Exp $";
-#endif
-
-#ifndef SMC_IRCC_H
-#define SMC_IRCC_H
-
-#define FIR_XMIT 1
-#define FIR_RECEIVE 2
-#define SIR_XMIT 3
-#define SIR_RECEIVE 4
-
-#define MASTER 0x07
-#define MASTER_POWERDOWN 1<<7
-#define MASTER_RESET 1<<6
-#define MASTER_INT_EN 1<<5
-#define MASTER_ERROR_RESET 1<<4
-
-/* Register block 0 */
-
-#define IIR 0x01
-#define IER 0x02
-#define LSR 0x03
-#define LCR_A 0x04
-#define LCR_B 0x05
-#define BSR 0x06
-
-#define IIR_ACTIVE_FRAME 1<<7
-#define IIR_EOM 1<<6
-#define IIR_RAW_MODE 1<<5
-#define IIR_FIFO 1<<4
-
-#define IER_ACTIVE_FRAME 1<<7
-#define IER_EOM 1<<6
-#define IER_RAW_MODE 1<<5
-#define IER_FIFO 1<<4
-
-#define LSR_UNDER_RUN 1<<7
-#define LSR_OVER_RUN 1<<6
-#define LSR_FRAME_ERROR 1<<5
-#define LSR_SIZE_ERROR 1<<4
-#define LSR_CRC_ERROR 1<<3
-#define LSR_FRAME_ABORT 1<<2
-
-#define LCR_A_FIFO_RESET 1<<7
-#define LCR_A_FAST 1<<6
-#define LCR_A_GP_DATA 1<<5
-#define LCR_A_RAW_TX 1<<4
-#define LCR_A_RAW_RX 1<<3
-#define LCR_A_ABORT 1<<2
-#define LCR_A_DATA_DONE 1<<1
-
-#define LCR_B_SCE_MODE_DISABLED 0x00<<6
-#define LCR_B_SCE_MODE_TRANSMIT 0x01<<6
-#define LCR_B_SCE_MODE_RECEIVE 0x02<<6
-#define LCR_B_SCE_MODE_UNDEFINED 0x03<<6
-#define LCR_B_SIP_ENABLE 1<<5
-#define LCR_B_BRICK_WALL 1<<4
-
-#define BSR_NOT_EMPTY 1<<7
-#define BSR_FIFO_FULL 1<<6
-#define BSR_TIMEOUT 1<<5
-
-/* Register block 1 */
-
-#define SCE_CFG_A 0x00
-#define SCE_CFG_B 0x01
-#define FIFO_THRESHOLD 0x02
-
-#define CFG_A_AUX_IR 0x01<<7
-#define CFG_A_HALF_DUPLEX 0x01<<2
-#define CFG_A_TX_POLARITY 0x01<<1
-#define CFG_A_RX_POLARITY 0x01
-
-#define CFG_A_COM 0x00<<3
-#define CFG_A_IRDA_SIR_A 0x01<<3
-#define CFG_A_ASK_SIR 0x02<<3
-#define CFG_A_IRDA_SIR_B 0x03<<3
-#define CFG_A_IRDA_HDLC 0x04<<3
-#define CFG_A_IRDA_4PPM 0x05<<3
-#define CFG_A_CONSUMER 0x06<<3
-#define CFG_A_RAW_IR 0x07<<3
-#define CFG_A_OTHER 0x08<<3
-
-#define IR_HDLC 0x04
-#define IR_4PPM 0x01
-#define IR_CONSUMER 0x02
-
-#define CFG_B_LOOPBACK 0x01<<5
-#define CFG_B_LPBCK_TX_CRC 0x01<<4
-#define CFG_B_NOWAIT 0x01<<3
-#define CFB_B_STRING_MOVE 0x01<<2
-#define CFG_B_DMA_BURST 0x01<<1
-#define CFG_B_DMA_ENABLE 0x01
-
-#define CFG_B_MUX_COM 0x00<<6
-#define CFG_B_MUX_IR 0x01<<6
-#define CFG_B_MUX_AUX 0x02<<6
-#define CFG_B_INACTIVE 0x03<<6
-
-/* Register block 2 - Consumer IR - not used */
-
-/* Register block 3 - Identification Registers! */
-
-#define SMSC_ID_HIGH 0x00 /* 0x10 */
-#define SMSC_ID_LOW 0x01 /* 0xB8 */
-#define CHIP_ID 0x02 /* 0xF1 */
-#define VERSION_NUMBER 0x03 /* 0x01 */
-#define HOST_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
-
-/* Register block 4 - IrDA */
-#define IR_CONTROL 0x00
-#define BOF_COUNT_LO 0x01
-#define BRICK_WALL_CNT_LO 0x02
-#define BRICK_TX_CNT_HI 0x03
-#define TX_DATA_SIZE_LO 0x04
-#define RX_DATA_SIZE_HI 0x05
-#define RX_DATA_SIZE_LO 0x06
-
-#define SELECT_1152 0x01<<7
-#define CRC_SELECT 0x01<<6
-
-#endif
diff -u --recursive --new-file v2.3.5/linux/include/net/neighbour.h linux/include/net/neighbour.h
--- v2.3.5/linux/include/net/neighbour.h Tue May 11 13:05:00 1999
+++ linux/include/net/neighbour.h Wed Jun 9 14:45:36 1999
@@ -96,7 +96,8 @@
X __u8 flags;
X __u8 nud_state;
X __u8 type;
- __u8 probes;
+ atomic_t probes;
+ rwlock_t lock;
X unsigned char ha[MAX_ADDR_LEN];
X struct hh_cache *hh;
X atomic_t refcnt;
@@ -155,7 +156,7 @@
X struct timer_list proxy_timer;
X struct sk_buff_head proxy_queue;
X int entries;
- atomic_t lock;
+ rwlock_t lock;
X unsigned long last_rand;
X struct neigh_parms *parms_list;
X struct neigh_statistics stats;
@@ -165,9 +166,12 @@
X
X extern void neigh_table_init(struct neigh_table *tbl);
X extern int neigh_table_clear(struct neigh_table *tbl);
-extern struct neighbour *__neigh_lookup(struct neigh_table *tbl,
- const void *pkey, struct device *dev,
- int creat);
+extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
+ const void *pkey,
+ struct device *dev);
+extern struct neighbour * neigh_create(struct neigh_table *tbl,
+ const void *pkey,
+ struct device *dev);
X extern void neigh_destroy(struct neighbour *neigh);
X extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
X extern int neigh_update(struct neighbour *neigh, u8 *lladdr, u8 new, int override, int arp);
@@ -226,16 +230,6 @@
X neigh->confirmed = jiffies;
X }
X
-extern __inline__ struct neighbour *
-neigh_lookup(struct neigh_table *tbl, const void *pkey, struct device *dev)
-{
- struct neighbour *neigh;
- start_bh_atomic();
- neigh = __neigh_lookup(tbl, pkey, dev, 0);
- end_bh_atomic();
- return neigh;
-}
-
X extern __inline__ int neigh_is_connected(struct neighbour *neigh)
X {
X return neigh->nud_state&NUD_CONNECTED;
@@ -254,17 +248,16 @@


X return 0;
X }
X

-extern __inline__ void neigh_table_lock(struct neigh_table *tbl)
+extern __inline__ struct neighbour *
+__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct device *dev, int creat)
X {
- atomic_inc(&tbl->lock);
- synchronize_bh();
-}
+ struct neighbour *n = neigh_lookup(tbl, pkey, dev);
X
-extern __inline__ void neigh_table_unlock(struct neigh_table *tbl)
-{
- atomic_dec(&tbl->lock);
-}
+ if (n || !creat)
+ return n;
X
+ return neigh_create(tbl, pkey, dev);
+}
X
X #endif
X #endif
diff -u --recursive --new-file v2.3.5/linux/include/net/pkt_cls.h linux/include/net/pkt_cls.h
--- v2.3.5/linux/include/net/pkt_cls.h Thu Mar 25 09:23:34 1999
+++ linux/include/net/pkt_cls.h Wed Jun 9 14:45:36 1999
@@ -77,14 +77,11 @@


X return -1;
X }
X

-extern __inline__ unsigned long cls_set_class(unsigned long *clp, unsigned long cl)
-{
- cl = xchg(clp, cl);
- synchronize_bh();
- return cl;
-}
+
X
X extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
X extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+
+
X
X #endif
diff -u --recursive --new-file v2.3.5/linux/include/net/pkt_sched.h linux/include/net/pkt_sched.h
--- v2.3.5/linux/include/net/pkt_sched.h Thu Apr 22 19:45:19 1999
+++ linux/include/net/pkt_sched.h Wed Jun 9 14:45:36 1999
@@ -66,9 +66,12 @@
X struct Qdisc_head
X {
X struct Qdisc_head *forw;
+ struct Qdisc_head *back;
X };
X
X extern struct Qdisc_head qdisc_head;
+extern spinlock_t qdisc_runqueue_lock;
+extern rwlock_t qdisc_tree_lock;
X
X struct Qdisc
X {
@@ -106,6 +109,46 @@
X int refcnt;
X };
X
+extern __inline__ void sch_tree_lock(struct Qdisc *q)
+{
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&q->dev->queue_lock);
+}
+
+extern __inline__ void sch_tree_unlock(struct Qdisc *q)
+{
+ spin_unlock_bh(&q->dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
+}
+
+extern __inline__ void tcf_tree_lock(struct tcf_proto *tp)
+{
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&tp->q->dev->queue_lock);
+}
+
+extern __inline__ void tcf_tree_unlock(struct tcf_proto *tp)
+{
+ spin_unlock_bh(&tp->q->dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
+}
+
+
+extern __inline__ unsigned long
+cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl)
+{
+ tcf_tree_lock(tp);
+ cl = xchg(clp, cl);
+ tcf_tree_unlock(tp);
+ return cl;
+}
+
+extern __inline__ unsigned long
+__cls_set_class(unsigned long *clp, unsigned long cl)
+{
+ return xchg(clp, cl);
+}
+
X
X /*
X Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
@@ -343,12 +386,14 @@
X u32 toks;
X u32 ptoks;
X psched_time_t t_c;
+ spinlock_t lock;
X struct qdisc_rate_table *R_tab;
X struct qdisc_rate_table *P_tab;
X
X struct tc_stats stats;
X };
X
+extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st);
X extern void tcf_police_destroy(struct tcf_police *p);
X extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
X extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
@@ -384,20 +429,56 @@
X int tc_filter_init(void);
X int pktsched_init(void);
X
-void qdisc_run_queues(void);
-int qdisc_restart(struct device *dev);
+extern void qdisc_run_queues(void);
+extern int qdisc_restart(struct device *dev);
+
+extern spinlock_t qdisc_runqueue_lock;
+
+/* Is it on run list? Reliable only under qdisc_runqueue_lock. */
+
+extern __inline__ int qdisc_on_runqueue(struct Qdisc *q)
+{
+ return q->h.forw != NULL;
+}
+
+/* Is run list not empty? Reliable only under qdisc_runqueue_lock. */
+
+extern __inline__ int qdisc_pending(void)
+{
+ return qdisc_head.forw != &qdisc_head;
+}
+
+/* Add qdisc to tail of run list. Called with BH, disabled on this CPU */
+
+extern __inline__ void qdisc_run(struct Qdisc *q)
+{
+ spin_lock(&qdisc_runqueue_lock);
+ if (!qdisc_on_runqueue(q)) {
+ q->h.forw = &qdisc_head;
+ q->h.back = qdisc_head.back;
+ qdisc_head.back->forw = &q->h;
+ qdisc_head.back = &q->h;
+ }
+ spin_unlock(&qdisc_runqueue_lock);
+}
+
+/* If the device is not throttled, restart it and add to run list.
+ * BH must be disabled on this CPU.
+ */
X
X extern __inline__ void qdisc_wakeup(struct device *dev)
X {
X if (!dev->tbusy) {
- struct Qdisc *q = dev->qdisc;
- if (qdisc_restart(dev) && q->h.forw == NULL) {
- q->h.forw = qdisc_head.forw;
- qdisc_head.forw = &q->h;
- }
+ spin_lock(&dev->queue_lock);
+ if (qdisc_restart(dev))
+ qdisc_run(dev->qdisc);
+ spin_unlock(&dev->queue_lock);
X }
X }
X
+/* Calculate maximal size of packet seen by hard_start_xmit
+ routine of this device.
+ */
X extern __inline__ unsigned psched_mtu(struct device *dev)
X {
X unsigned mtu = dev->mtu;
diff -u --recursive --new-file v2.3.5/linux/include/net/route.h linux/include/net/route.h
--- v2.3.5/linux/include/net/route.h Mon May 31 22:28:07 1999
+++ linux/include/net/route.h Wed Jun 9 14:45:36 1999
@@ -35,13 +35,6 @@
X
X #define RT_HASH_DIVISOR 256
X
-/*
- * Prevents LRU trashing, entries considered equivalent,
- * if the difference between last use times is less then this number.
- */
-#define RT_CACHE_BUBBLE_THRESHOLD (5*HZ)
-
-
X #define RTO_ONLINK 0x01
X #define RTO_TPROXY 0x80000000
X
@@ -103,6 +96,7 @@
X };
X
X extern struct ip_rt_acct ip_rt_acct[256];
+extern rwlock_t ip_rt_acct_lock;
X
X extern void ip_rt_init(void);
X extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
diff -u --recursive --new-file v2.3.5/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.3.5/linux/include/net/tcp.h Mon May 31 22:28:07 1999
+++ linux/include/net/tcp.h Tue Jun 8 23:04:46 1999
@@ -289,7 +289,7 @@
X #define TCP_PROBEWAIT_LEN (1*HZ)/* time to wait between probes when
X * I've got something to write and
X * there is no window */
-#define TCP_KEEPALIVE_TIME (180*60*HZ) /* two hours */
+#define TCP_KEEPALIVE_TIME (120*60*HZ) /* two hours */
X #define TCP_KEEPALIVE_PROBES 9 /* Max of 9 keepalive probes */
X #define TCP_KEEPALIVE_PERIOD ((75*HZ)>>2) /* period of keepalive check */
X
diff -u --recursive --new-file v2.3.5/linux/include/net/udp.h linux/include/net/udp.h
--- v2.3.5/linux/include/net/udp.h Sun Nov 30 14:00:39 1997
+++ linux/include/net/udp.h Tue Jun 8 17:58:03 1999
@@ -34,8 +34,14 @@
X
X extern unsigned short udp_good_socknum(void);
X
-#define UDP_NO_CHECK 0
+/* Note: this must match 'valbool' in sock_setsockopt */
+#define UDP_CSUM_NOXMIT 1
X
+/* Used by SunRPC/xprt layer. */
+#define UDP_CSUM_NORCV 2
+
+/* Default, as per the RFC, is to always do csums. */
+#define UDP_CSUM_DEFAULT 0
X
X extern struct proto udp_prot;
X
diff -u --recursive --new-file v2.3.5/linux/include/scsi/scsicam.h linux/include/scsi/scsicam.h
--- v2.3.5/linux/include/scsi/scsicam.h Thu Jun 12 15:29:27 1997
+++ linux/include/scsi/scsicam.h Wed Jun 9 16:59:16 1999
@@ -14,4 +14,6 @@
X #define SCSICAM_H
X #include <linux/kdev_t.h>
X extern int scsicam_bios_param (Disk *disk, kdev_t dev, int *ip);
+extern int scsi_partsize(struct buffer_head *bh, unsigned long capacity,
+ unsigned int *cyls, unsigned int *hds, unsigned int *secs);
X #endif /* def SCSICAM_H */
diff -u --recursive --new-file v2.3.5/linux/include/scsi/sg.h linux/include/scsi/sg.h
--- v2.3.5/linux/include/scsi/sg.h Fri May 7 11:05:30 1999
+++ linux/include/scsi/sg.h Mon Jun 7 16:20:36 1999
@@ -12,10 +12,16 @@
X * Copyright (C) 1998, 1999 Douglas Gilbert
X
X
- Version: 2.1.32 (990501)
- This version for later 2.1.x series and 2.2.x kernels
+ Version: 2.1.34 (990603)
+ This version for later 2.1.x and 2.2.x series kernels
X D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au)
X
+ Changes since 2.1.33 (990521)
+ - implement SG_SET_RESERVED_SIZE and associated memory re-org.
+ - add SG_NEXT_CMD_LEN to override SCSI command lengths
+ - add SG_GET_VERSION_NUM to get version expressed as an integer
+ Changes since 2.1.32 (990501)
+ - fix race condition in sg_read() and sg_open()
X Changes since 2.1.31 (990327)
X - add ioctls SG_GET_UNDERRUN_FLAG and _SET_. Change the default
X to _not_ flag underruns (affects aic7xxx driver)
@@ -25,24 +31,6 @@
X Changes since 2.1.30 (990320)
X - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
X - increase max allowable mid-level pool usage
- Changes since 2.1.21 (990315)
- - skipped to 2.1.30 indicating interface change (revert to 2.1.9)
- - remove attempt to accomodate cdrecord 1.8, will fix app
- - keep SG_?ET_RESERVED_SIZE naming for clarity
- Changes since 2.1.20 (990313)
- - ommission: left out logic for SG_?ET_ALT_INTERFACE, now added
- Changes since 2.1.9 (990309)
- - skipped to version 2.1.20 to indicate some interface changes
- - incorporate sg changes to make cdrecord 1.8 work (had its
- own patches that were different from the original)
- - change SG_?ET_BUFF_SIZE to SG_?ET_RESERVED_SIZE for clarity
- Changes since 2.1.8 (990303)
- - debug ">9" option dumps debug for _all_ active sg devices
- - increase allowable dma pool usage + increase minimum threshhold
- - pad out sg_scsi_id structure
- Changes since 2.1.7 (990227)
- - command queuing now "non-default" [back. compat. with cdparanoia]
- - Tighten access on some ioctls
X
X
X New features and changes:
@@ -52,24 +40,32 @@
X - the SCSI target, host and driver status are returned
X in unused fields of sg_header (maintaining its original size).
X - asynchronous notification support added (SIGPOLL, SIGIO) for
- read()s ( write()s should never block).
- - pack_id logic added so read() can be made to wait for a specific
- pack_id.
+ read()s (write()s should never block).
+ - pack_id logic added so read() can wait for a specific pack_id.
X - uses memory > ISA_DMA_THRESHOLD if adapter allows it (e.g. a
X pci scsi adapter).
X - this driver no longer uses a single SG_BIG_BUFF sized buffer
- obtained at driver/module init time. Rather it obtains a
- SG_SCATTER_SZ buffer when a fd is open()ed and frees it at
- the corresponding release() (ie pr fd). Hence open() can return
- ENOMEM! If write() request > SG_SCATTER_SZ bytes for data then
- it can fail with ENOMEM as well (if so, scale back).
+ obtained at driver/module init time. Rather it tries to obtain a
+ SG_DEF_RESERVED_SIZE buffer when a fd is open()ed and frees it
+ at the corresponding release() (ie per fd). Actually the "buffer"
+ may be a collection of buffers if scatter-gather is being used.
+ - add SG_SET_RESERVED_SIZE ioctl allowing the user to request a
+ large buffer for duration of current file descriptor's lifetime.
+ - SG_GET_RESERVED_SIZE ioctl can be used to find out how much
+ actually has been reserved.
+ - add SG_NEXT_CMD_LEN ioctl to override SCSI command length on
+ the next write() to this file descriptor.
+ - SG_GET_RESERVED_SIZE's presence as a symbol can be used for
+ compile time identification of the version 2 sg driver.
+ However, it is recommended that run time identification based on
+ calling the ioctl of the same name is a more flexible and
+ safer approach.
X - adds several ioctl calls, see ioctl section below.
- - SG_SCATTER_SZ's presence indicates this version of "sg" driver.
X
X Good documentation on the original "sg" device interface and usage can be
- found in the Linux HOWTO document: "SCSI Programming HOWTO" by Heiko
- Eissfeldt; last updated 7 May 1996. I will add more info on using the
- extensions in this driver as required. A quick summary:
+ found in the Linux HOWTO document: "SCSI Programming HOWTO" (version 0.5)
+ by Heiko Eissfeldt; last updated 7 May 1996. Here is a quick summary of
+ sg basics:
X An SG device is accessed by writing SCSI commands plus any associated
X outgoing data to it; the resulting status codes and any incoming data
X are then obtained by a read call. The device can be opened O_NONBLOCK
@@ -88,38 +84,37 @@
X The given SCSI command has its LUN field overwritten internally by the
X value associated with the device that has been opened.
X
- Memory (RAM) is used within this driver for direct memory access (DMA)
- in transferring data to and from the SCSI device. The dreaded ENOMEM
- seems to be more prevalent under early 2.2.x kernels than under the
- 2.0.x kernel series. For a given (large) transfer the memory obtained by
- this driver must be contiguous or scatter-gather must be used (if
- supported by the adapter). [Furthermore, ISA SCSI adapters can only use
- memory below the 16MB level on a i386.]
- This driver tries hard to find some suitable memory before admitting
- defeat and returning ENOMEM. All is not lost if application writers
- then back off the amount they are requesting. The value returned by
- the SG_GET_RESERVED_SIZE ioctl is guaranteed to be available (one
- per fd). This driver does the following:
- - attempts to reserve a SG_SCATTER_SZ sized buffer on open(). The
- actual amount reserved is given by the SG_GET_RESERVED_SIZE ioctl().
- - each write() needs to reserve a DMA buffer of the size of the
- data buffer indicated (excluding sg_header and command overhead).
- This buffer, depending on its size, adapter type (ISA or not) and
- the amount of memory available will be obtained from the kernel
- directly (get_free_pages or kmalloc) or the from the scsi mid-level
- dma pool (taking care not to exhaust it).
- If the buffer requested is > SG_SCATTER_SZ or memory is tight then
- scatter-gather will be used if supported by the adapter.
- - write() will also attempt to use the buffer reserved on open()
- if it is large enough.
- The above strategy ensures that a write() can always depend on a buffer
- of the size indicated by the SG_GET_RESERVED_SIZE ioctl() (which could be
- 0, but at least the app knows things are tight in advance).
- Hence application writers can adopt quite aggressive strategies (e.g.
- requesting 512KB) and scale them back in the face of ENOMEM errors.
- N.B. Queuing up commands also ties up kernel memory.
+ This device currently uses "indirect IO" in the sense that data is
+ DMAed into kernel buffers from the hardware and afterwards is
+ transferred into the user space (or vice versa if you are writing).
+ Transfer speeds or up to 20 to 30MBytes/sec have been measured using
+ indirect IO. For faster throughputs "direct IO" which cuts out the
+ double handling of data is required. This will also need a new interface.
+
+ Grabbing memory for those kernel buffers used in this driver for DMA may
+ cause the dreaded ENOMEM error. This error seems to be more prevalent
+ under early 2.2.x kernels than under the 2.0.x kernel series. For a given
+ (large) transfer the memory obtained by this driver must be contiguous or
+ scatter-gather must be used (if supported by the adapter). [Furthermore,
+ ISA SCSI adapters can only use memory below the 16MB level on a i386.]
+
+ When a "sg" device is open()ed O_RDWR then this driver will attempt to
+ reserve a buffer of SG_DEF_RESERVED_SIZE that will be used by subsequent
+ write()s on this file descriptor as long as:
+ - it is not already in use (eg when command queuing is in use)
+ - the write() does not call for a buffer size larger than the
+ reserved size.
+ In these cases the write() will attempt to find the memory it needs for
+ DMA buffers dynamically and in the worst case will fail with ENOMEM.
+ The amount of memory actually reserved depends on various dynamic factors
+ and can be checked with the SG_GET_RESERVED_SIZE ioctl(). [In a very
+ tight memory situation it may yield 0!] The size of the reserved buffer
+ can be changed with the SG_SET_RESERVED_SIZE ioctl(). It should be
+ followed with a call to the SG_GET_RESERVED_SIZE ioctl() to find out how
+ much was actually reserved.
X
- More documentation can be found at www.torque.net/sg
+ More documentation plus test and utility programs can be found at
+ http://www.torque.net/sg
X */
X
X #define SG_MAX_SENSE 16 /* too little, unlikely to change in 2.2.x */
@@ -129,7 +124,7 @@
X int pack_len; /* [o] reply_len (ie useless), ignored as input */
X int reply_len; /* [i] max length of expected reply (inc. sg_header) */
X int pack_id; /* [io] id number of packet (use ints >= 0) */
- int result; /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */
+ int result; /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
X unsigned int twelve_byte:1;
X /* [i] Force 12 byte command length for group 6 & 7 commands */
X unsigned int target_status:5; /* [o] scsi status from target */
@@ -154,9 +149,9 @@
X int unused3;
X } Sg_scsi_id;
X
-/* ioctls ( _GET_s yield result via 'int *' 3rd argument unless
- otherwise indicated */
-#define SG_SET_TIMEOUT 0x2201 /* unit: jiffies, 10ms on i386 */
+/* IOCTLs: ( _GET_s yield result via 'int *' 3rd argument unless
+ otherwise indicated) */
+#define SG_SET_TIMEOUT 0x2201 /* unit: jiffies (10ms on i386) */
X #define SG_GET_TIMEOUT 0x2202 /* yield timeout as _return_ value */
X
X #define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */
@@ -165,23 +160,21 @@
X #define SG_SET_TRANSFORM 0x2204
X #define SG_GET_TRANSFORM 0x2205
X
-#define SG_SET_RESERVED_SIZE 0x2275 /* currently ignored, future addition */
-/* Following yields buffer reserved by open(): 0 <= x <= SG_SCATTER_SZ */
-#define SG_GET_RESERVED_SIZE 0x2272
+#define SG_SET_RESERVED_SIZE 0x2275 /* request a new reserved buffer size */
+#define SG_GET_RESERVED_SIZE 0x2272 /* actual size of reserved buffer */
X
X /* The following ioctl takes a 'Sg_scsi_id *' object as its 3rd argument. */
-#define SG_GET_SCSI_ID 0x2276 /* Yields fd's bus,chan,dev,lun+type */
+#define SG_GET_SCSI_ID 0x2276 /* Yields fd's bus, chan, dev, lun + type */
X /* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */
X
-/* Override adapter setting and always DMA using low memory ( <16MB on i386).
- Default is 0 (off - use adapter setting) */
+/* Override host setting and always DMA using low memory ( <16MB on i386) */
X #define SG_SET_FORCE_LOW_DMA 0x2279 /* 0-> use adapter setting, 1-> force */
X #define SG_GET_LOW_DMA 0x227a /* 0-> use all ram for dma; 1-> low dma ram */
X
X /* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which
X will attempt to read that pack_id or block (or return EAGAIN). If
X pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
- (default) then pack_id ignored by read() and oldest readable fetched. */
+ then pack_id ignored by read() and oldest readable fetched. */
X #define SG_SET_FORCE_PACK_ID 0x227b
X #define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */
X
@@ -194,43 +187,47 @@
X /* Yields max scatter gather tablesize allowed by current host adapter */
X #define SG_GET_SG_TABLESIZE 0x227F /* 0 implies can't do scatter gather */
X
-/* Control whether sequencing per file descriptor (default) or per device */
-#define SG_GET_MERGE_FD 0x2274 /* 0-> per fd (default), 1-> per device */
+/* Control whether sequencing per file descriptor or per device */
+#define SG_GET_MERGE_FD 0x2274 /* 0-> per fd, 1-> per device */
X #define SG_SET_MERGE_FD 0x2273 /* Attempt to change sequencing state,
- if more than 1 fd open on device, will fail with EBUSY */
+ if more than current fd open on device, will fail with EBUSY */
X
X /* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q) */
X #define SG_GET_COMMAND_Q 0x2270 /* Yields 0 (queuing off) or 1 (on) */


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

echo 'End of part 21'
echo 'File patch-2.3.6 is continued in part 22'
echo 22 > _shar_seq_.tmp

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part22

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


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

if test "$Scheck" != 22; then


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

X #define SG_SET_COMMAND_Q 0x2271 /* Change queuing state with 0 or 1 */
X
-/* Get/set whether DMA underrun will cause an error (DID_ERROR) [this only
- currently applies to the [much-used] aic7xxx driver) */
+/* Get/set whether DMA underrun will cause an error (DID_ERROR). This only
+ currently applies to the [much-used] aic7xxx driver. */
X #define SG_GET_UNDERRUN_FLAG 0x2280 /* Yields 0 (don't flag) or 1 (flag) */
X #define SG_SET_UNDERRUN_FLAG 0x2281 /* Change flag underrun state */
X
+#define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */
+#define SG_NEXT_CMD_LEN 0x2283 /* override SCSI command length with given
+ number on the next write() on this file descriptor */
+
+
+#define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */
+/* Largest size (in bytes) a single scatter-gather list element can have.
+ The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
+ i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
+ by adapter then this value is the largest data block that can be
+ read/written by a single scsi command. The user can find the value of
+ PAGE_SIZE by calling getpagesize() defined in unistd.h . */
X
X #define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
X #define SG_DEFAULT_RETRIES 1
X
-/* Default modes, commented if they differ from original sg driver */
+/* Defaults, commented if they differ from original sg driver */
X #define SG_DEF_COMMAND_Q 0
X #define SG_DEF_MERGE_FD 0 /* was 1 -> per device sequencing */
X #define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */
X #define SG_DEF_FORCE_PACK_ID 0
X #define SG_DEF_UNDERRUN_FLAG 0
+#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ
X
X /* maximum outstanding requests, write() yields EDOM if exceeded */
X #define SG_MAX_QUEUE 16
X
-#define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */
-/* Largest size (in bytes) a single scatter-gather list element can have.
- The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
- i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
- by adapter then this value is the largest data block that can be
- read/written by a single scsi command. Max number of scatter-gather
- list elements seems to be limited to 255. */
-
-#define SG_BIG_BUFF SG_SCATTER_SZ /* for backward compatibility */
-/* #define SG_BIG_BUFF (SG_SCATTER_SZ * 8) */ /* =256KB, if you want */
+#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE /* for backward compatibility */
X
X #endif
diff -u --recursive --new-file v2.3.5/linux/ipc/msg.c linux/ipc/msg.c
--- v2.3.5/linux/ipc/msg.c Fri May 14 18:55:30 1999
+++ linux/ipc/msg.c Mon Jun 7 12:20:50 1999
@@ -8,6 +8,7 @@
X * Fixed up the unchecked user space derefs
X * Copyright (C) 1998 Alan Cox & Andi Kleen
X *
+ * /proc/sysvipc/msg support (c) 1999 Dragos Acostachioaie <dra...@iname.com>
X */
X
X #include <linux/malloc.h>
@@ -15,6 +16,7 @@
X #include <linux/interrupt.h>
X #include <linux/smp_lock.h>
X #include <linux/init.h>
+#include <linux/proc_fs.h>
X
X #include <asm/uaccess.h>
X
@@ -23,6 +25,9 @@
X static void freeque (int id);
X static int newque (key_t key, int msgflg);
X static int findkey (key_t key);
+#ifdef CONFIG_PROC_FS
+static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+#endif
X
X static struct msqid_ds *msgque[MSGMNI];
X static int msgbytes = 0;
@@ -35,11 +40,18 @@
X void __init msg_init (void)
X {
X int id;
-
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent;
+#endif
+
X for (id = 0; id < MSGMNI; id++)
X msgque[id] = (struct msqid_ds *) IPC_UNUSED;
X msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
X init_waitqueue_head(&msg_lock);
+#ifdef CONFIG_PROC_FS
+ ent = create_proc_entry("sysvipc/msg", 0, 0);
+ ent->read_proc = sysvipc_msg_read_proc;
+#endif
X return;
X }
X
@@ -492,3 +504,49 @@


X return err;
X }
X

+#ifdef CONFIG_PROC_FS
+static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ off_t pos = 0;
+ off_t begin = 0;
+ int i, len = 0;
+
+ len += sprintf(buffer, " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n");
+
+ for(i = 0; i < MSGMNI; i++)
+ if(msgque[i] != IPC_UNUSED) {
+ len += sprintf(buffer + len, "%10d %10d %4o %5u %5u %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
+ msgque[i]->msg_perm.key,
+ msgque[i]->msg_perm.seq * MSGMNI + i,
+ msgque[i]->msg_perm.mode,
+ msgque[i]->msg_cbytes,
+ msgque[i]->msg_qnum,
+ msgque[i]->msg_lspid,
+ msgque[i]->msg_lrpid,
+ msgque[i]->msg_perm.uid,
+ msgque[i]->msg_perm.gid,
+ msgque[i]->msg_perm.cuid,
+ msgque[i]->msg_perm.cgid,
+ msgque[i]->msg_stime,
+ msgque[i]->msg_rtime,
+ msgque[i]->msg_ctime);
+
+ pos += len;
+ if(pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if(pos > offset + length)
+ goto done;
+ }
+ *eof = 1;
+done:
+ *start = buffer + (offset - begin);
+ len -= (offset - begin);
+ if(len > length)
+ len = length;
+ if(len < 0)
+ len = 0;
+ return len;
+}
+#endif
diff -u --recursive --new-file v2.3.5/linux/ipc/sem.c linux/ipc/sem.c
--- v2.3.5/linux/ipc/sem.c Fri May 14 18:55:30 1999
+++ linux/ipc/sem.c Mon Jun 7 12:20:50 1999
@@ -48,11 +48,14 @@
X * better but only get the semops right which only wait for zero or
X * increase. If there are decrement operations in the operations
X * array we do the same as before.
+ *
+ * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dra...@iname.com>
X */
X
X #include <linux/malloc.h>
X #include <linux/smp_lock.h>
X #include <linux/init.h>
+#include <linux/proc_fs.h>
X
X #include <asm/uaccess.h>
X
@@ -60,6 +63,9 @@
X static int newary (key_t, int, int);
X static int findkey (key_t key);
X static void freeary (int id);
+#ifdef CONFIG_PROC_FS
+static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+#endif
X
X static struct semid_ds *semary[SEMMNI];
X static int used_sems = 0, used_semids = 0;
@@ -71,11 +77,18 @@
X void __init sem_init (void)
X {
X int i;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent;
+#endif
X
X init_waitqueue_head(&sem_lock);
X used_sems = used_semids = max_semid = sem_seq = 0;
X for (i = 0; i < SEMMNI; i++)
X semary[i] = (struct semid_ds *) IPC_UNUSED;
+#ifdef CONFIG_PROC_FS
+ ent = create_proc_entry("sysvipc/sem", 0, 0);
+ ent->read_proc = sysvipc_sem_read_proc;
+#endif
X return;
X }
X
@@ -785,3 +798,46 @@
X }
X current->semundo = NULL;
X }
+
+#ifdef CONFIG_PROC_FS
+static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ off_t pos = 0;
+ off_t begin = 0;
+ int i, len = 0;
+
+ len += sprintf(buffer, " key semid perms nsems uid gid cuid cgid otime ctime\n");
+
+ for(i = 0; i < SEMMNI; i++)
+ if(semary[i] != IPC_UNUSED) {
+ len += sprintf(buffer + len, "%10d %10d %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
+ semary[i]->sem_perm.key,
+ semary[i]->sem_perm.seq * SEMMNI + i,
+ semary[i]->sem_perm.mode,
+ semary[i]->sem_nsems,
+ semary[i]->sem_perm.uid,
+ semary[i]->sem_perm.gid,
+ semary[i]->sem_perm.cuid,
+ semary[i]->sem_perm.cgid,
+ semary[i]->sem_otime,
+ semary[i]->sem_ctime);
+
+ pos += len;
+ if(pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if(pos > offset + length)
+ goto done;
+ }
+ *eof = 1;
+done:
+ *start = buffer + (offset - begin);
+ len -= (offset - begin);
+ if(len > length)
+ len = length;
+ if(len < 0)
+ len = 0;
+ return len;
+}
+#endif
diff -u --recursive --new-file v2.3.5/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.5/linux/ipc/shm.c Fri May 14 18:55:30 1999
+++ linux/ipc/shm.c Mon Jun 7 12:20:50 1999
@@ -4,6 +4,8 @@
X * Many improvements/fixes by Bruno Haible.
X * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994.
X * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli.
+ *
+ * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie <dra...@iname.com>
X */
X
X #include <linux/malloc.h>
@@ -12,6 +14,7 @@
X #include <linux/smp_lock.h>
X #include <linux/init.h>
X #include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
X
X #include <asm/uaccess.h>
X #include <asm/pgtable.h>
@@ -26,6 +29,9 @@
X static void shm_close (struct vm_area_struct *shmd);
X static unsigned long shm_nopage(struct vm_area_struct *, unsigned long, int);
X static int shm_swapout(struct vm_area_struct *, struct page *);
+#ifdef CONFIG_PROC_FS
+static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+#endif
X
X static int shm_tot = 0; /* total number of shared memory pages */
X static int shm_rss = 0; /* number of shared memory pages that are in memory */
@@ -44,11 +50,18 @@
X void __init shm_init (void)
X {
X int id;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent;
+#endif
X
X for (id = 0; id < SHMMNI; id++)
X shm_segs[id] = (struct shmid_kernel *) IPC_UNUSED;
X shm_tot = shm_rss = shm_seq = max_shmid = used_segs = 0;
X init_waitqueue_head(&shm_lock);
+#ifdef CONFIG_PROC_FS
+ ent = create_proc_entry("sysvipc/shm", 0, 0);
+ ent->read_proc = sysvipc_shm_read_proc;
+#endif
X return;
X }
X
@@ -762,3 +775,50 @@
X return;
X }
X }
+
+#ifdef CONFIG_PROC_FS
+static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ off_t pos = 0;
+ off_t begin = 0;
+ int i, len = 0;
+
+ len += sprintf(buffer, " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n");
+
+ for(i = 0; i < SHMMNI; i++)
+ if(shm_segs[i] != IPC_UNUSED) {
+ len += sprintf(buffer + len, "%10d %10d %4o %10d %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n",
+ shm_segs[i]->u.shm_perm.key,
+ shm_segs[i]->u.shm_perm.seq * SHMMNI + i,
+ shm_segs[i]->u.shm_perm.mode,
+ shm_segs[i]->u.shm_segsz,
+ shm_segs[i]->u.shm_cpid,
+ shm_segs[i]->u.shm_lpid,
+ shm_segs[i]->u.shm_nattch,
+ shm_segs[i]->u.shm_perm.uid,
+ shm_segs[i]->u.shm_perm.gid,
+ shm_segs[i]->u.shm_perm.cuid,
+ shm_segs[i]->u.shm_perm.cgid,
+ shm_segs[i]->u.shm_atime,
+ shm_segs[i]->u.shm_dtime,
+ shm_segs[i]->u.shm_ctime);
+
+ pos += len;
+ if(pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if(pos > offset + length)
+ goto done;
+ }
+ *eof = 1;
+done:
+ *start = buffer + (offset - begin);
+ len -= (offset - begin);
+ if(len > length)
+ len = length;
+ if(len < 0)
+ len = 0;
+ return len;
+}
+#endif
diff -u --recursive --new-file v2.3.5/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.5/linux/kernel/ksyms.c Mon May 17 09:55:23 1999
+++ linux/kernel/ksyms.c Tue Jun 8 10:47:58 1999
@@ -82,6 +82,7 @@
X /* process memory management */
X EXPORT_SYMBOL(do_mmap);
X EXPORT_SYMBOL(do_munmap);
+EXPORT_SYMBOL(do_brk);
X EXPORT_SYMBOL(exit_mm);
X EXPORT_SYMBOL(exit_files);
X EXPORT_SYMBOL(exit_fs);
@@ -345,7 +346,7 @@
X
X /* Program loader interfaces */
X EXPORT_SYMBOL(setup_arg_pages);
-EXPORT_SYMBOL(copy_strings);
+EXPORT_SYMBOL(copy_strings_kernel);
X EXPORT_SYMBOL(do_execve);
X EXPORT_SYMBOL(flush_old_exec);
X EXPORT_SYMBOL(open_dentry);
diff -u --recursive --new-file v2.3.5/linux/kernel/signal.c linux/kernel/signal.c
--- v2.3.5/linux/kernel/signal.c Mon May 31 22:28:07 1999
+++ linux/kernel/signal.c Mon Jun 7 16:14:06 1999
@@ -11,6 +11,7 @@
X #include <linux/unistd.h>
X #include <linux/smp_lock.h>
X #include <linux/init.h>
+#include <linux/sched.h>
X
X #include <asm/uaccess.h>
X
@@ -324,7 +325,7 @@
X
X if (nr_queued_signals < max_queued_signals) {
X q = (struct signal_queue *)
- kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
+ kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
X }
X
X if (q) {
@@ -417,6 +418,7 @@
X if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN)
X t->sig->action[sig-1].sa.sa_handler = SIG_DFL;
X sigdelset(&t->blocked, sig);
+ recalc_sigpending(t);
X spin_unlock_irqrestore(&t->sigmask_lock, flags);
X
X return send_sig_info(sig, info, t);
diff -u --recursive --new-file v2.3.5/linux/kernel/sys.c linux/kernel/sys.c
--- v2.3.5/linux/kernel/sys.c Fri May 14 18:55:30 1999
+++ linux/kernel/sys.c Mon Jun 7 16:17:59 1999
@@ -901,6 +901,8 @@
X return -EINVAL;
X if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
X return -EFAULT;
+ if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
+ return -EINVAL;
X old_rlim = current->rlim + resource;
X if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
X (new_rlim.rlim_max > old_rlim->rlim_max)) &&
diff -u --recursive --new-file v2.3.5/linux/mm/memory.c linux/mm/memory.c
--- v2.3.5/linux/mm/memory.c Mon May 31 22:28:07 1999
+++ linux/mm/memory.c Tue Jun 8 14:09:57 1999
@@ -543,19 +543,6 @@
X }
X
X /*
- * sanity-check function..
- */
-static void put_page(pte_t * page_table, pte_t pte)
-{
- if (!pte_none(*page_table)) {
- free_page_and_swap_cache(pte_page(pte));
- return;
- }
-/* no need for flush_tlb */
- set_pte(page_table, pte);
-}
-
-/*
X * This routine is used to map in a page into an address space: needed by
X * execve() for the initial stack and environment pages.
X */
@@ -612,21 +599,15 @@
X * and potentially makes it more efficient.
X */
X static int do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long address, pte_t *page_table)
+ unsigned long address, pte_t *page_table, pte_t pte)
X {
- pte_t pte;
X unsigned long old_page, new_page;
X struct page * page_map;
X
- pte = *page_table;
X new_page = __get_free_page(GFP_USER);
- /* Did someone else copy this page for us while we slept? */
+ /* Did swap_out() unmapped the protected page while we slept? */
X if (pte_val(*page_table) != pte_val(pte))
X goto end_wp_page;
- if (!pte_present(pte))
- goto end_wp_page;
- if (pte_write(pte))
- goto end_wp_page;
X old_page = pte_page(pte);
X if (MAP_NR(old_page) >= max_mapnr)
X goto bad_wp_page;
@@ -650,36 +631,42 @@
X delete_from_swap_cache(page_map);
X /* FallThrough */
X case 1:
- /* We can release the kernel lock now.. */
- unlock_kernel();
-
X flush_cache_page(vma, address);
X set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
X flush_tlb_page(vma, address);
X end_wp_page:
+ /*
+ * We can release the kernel lock now.. Now swap_out will see
+ * a dirty page and so won't get confused and flush_tlb_page
+ * won't SMP race. -Andrea
+ */
+ unlock_kernel();
+
X if (new_page)
X free_page(new_page);
X return 1;
X }
X
- unlock_kernel();
X if (!new_page)
- return 0;
+ goto no_new_page;
X
- if (PageReserved(mem_map + MAP_NR(old_page)))
+ if (PageReserved(page_map))
X ++vma->vm_mm->rss;
X copy_cow_page(old_page,new_page);
X flush_page_to_ram(old_page);
X flush_page_to_ram(new_page);
X flush_cache_page(vma, address);
X set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
- free_page(old_page);
X flush_tlb_page(vma, address);
+ unlock_kernel();
+ __free_page(page_map);
X return 1;
X
X bad_wp_page:
X printk("do_wp_page: bogus page at address %08lx (%08lx)\n",address,old_page);
X send_sig(SIGKILL, tsk, 1);
+no_new_page:
+ unlock_kernel();
X if (new_page)
X free_page(new_page);
X return 0;
@@ -816,7 +803,7 @@
X tsk->min_flt++;
X flush_page_to_ram(page);
X }
- put_page(page_table, entry);
+ set_pte(page_table, entry);
X return 1;
X }
X
@@ -874,7 +861,7 @@
X } else if (atomic_read(&mem_map[MAP_NR(page)].count) > 1 &&
X !(vma->vm_flags & VM_SHARED))
X entry = pte_wrprotect(entry);
- put_page(page_table, entry);
+ set_pte(page_table, entry);
X /* no need to invalidate: a not-present page shouldn't be cached */
X return 1;
X }
@@ -908,7 +895,7 @@
X flush_tlb_page(vma, address);
X if (write_access) {
X if (!pte_write(entry))
- return do_wp_page(tsk, vma, address, pte);
+ return do_wp_page(tsk, vma, address, pte, entry);
X
X entry = pte_mkdirty(entry);
X set_pte(pte, entry);
diff -u --recursive --new-file v2.3.5/linux/mm/mmap.c linux/mm/mmap.c
--- v2.3.5/linux/mm/mmap.c Mon May 31 22:28:07 1999
+++ linux/mm/mmap.c Mon Jun 7 11:15:33 1999
@@ -84,6 +84,13 @@
X }
X }
X
+/*
+ * sys_brk() for the most part doesn't need the global kernel
+ * lock, except when an application is doing something nasty
+ * like trying to un-brk an area that has already been mapped
+ * to a regular file. in this case, the unmapping will need
+ * to invoke file system routines that need the global lock.
+ */
X asmlinkage unsigned long sys_brk(unsigned long brk)
X {
X unsigned long rlim, retval;
@@ -92,20 +99,6 @@
X
X down(&mm->mmap_sem);
X
- /*
- * This lock-kernel is one of the main contention points for
- * certain normal loads. And it really should not be here: almost
- * everything in brk()/mmap()/munmap() is protected sufficiently by
- * the mmap semaphore that we got above.
- *
- * We should move this into the few things that really want the
- * lock, namely anything that actually touches a file descriptor
- * etc. We can do all the normal anonymous mapping cases without
- * ever getting the lock at all - the actual memory management
- * code is already completely thread-safe.
- */
- lock_kernel();
-
X if (brk < mm->end_code)


X goto out;
X newbrk = PAGE_ALIGN(brk);

@@ -134,15 +127,12 @@
X goto out;
X
X /* Ok, looks good - let it rip. */
- if (do_mmap(NULL, oldbrk, newbrk-oldbrk,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0) != oldbrk)
+ if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
X goto out;
X set_brk:


X mm->brk = brk;

X out:
X retval = mm->brk;
- unlock_kernel();
X up(&mm->mmap_sem);
X return retval;
X }
@@ -470,6 +460,28 @@
X return NULL;
X }
X
+struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
+{
+ struct vm_area_struct * vma;
+ unsigned long start;
+
+ addr &= PAGE_MASK;
+ vma = find_vma(tsk->mm,addr);
+ if (!vma)
+ return NULL;
+ if (vma->vm_start <= addr)
+ return vma;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ return NULL;
+ start = vma->vm_start;
+ if (expand_stack(vma, addr))
+ return NULL;
+ if (vma->vm_flags & VM_LOCKED) {
+ make_pages_present(addr, start);
+ }
+ return vma;
+}
+
X /* Normal function to fix up a mapping
X * This function is the default for when an area has no specific
X * function. This may be used as part of a more specific routine.
@@ -665,6 +677,8 @@
X end = end > mpnt->vm_end ? mpnt->vm_end : end;
X size = end - st;
X
+ lock_kernel();
+
X if (mpnt->vm_ops && mpnt->vm_ops->unmap)
X mpnt->vm_ops->unmap(mpnt, st, size);
X
@@ -679,6 +693,8 @@
X * Fix the mapping, and free the old area if it wasn't reused.
X */
X extra = unmap_fixup(mpnt, st, size, extra);
+
+ unlock_kernel();
X }
X
X /* Release the extra vma struct if it wasn't used */
@@ -696,11 +712,85 @@
X int ret;


X
X down(&current->mm->mmap_sem);
- lock_kernel();

X ret = do_munmap(addr, len);


- unlock_kernel();
X up(&current->mm->mmap_sem);

X return ret;
+}
+
+/*
+ * this is really a simplified "do_mmap". it only handles
+ * anonymous maps. eventually we may be able to do some
+ * brk-specific accounting here.
+ */
+unsigned long do_brk(unsigned long addr, unsigned long len)
+{
+ struct mm_struct * mm = current->mm;
+ struct vm_area_struct * vma;
+ unsigned long flags, retval;
+
+ /*
+ * mlock MCL_FUTURE?
+ */
+ if (mm->def_flags & VM_LOCKED) {
+ unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+ locked += len;
+ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ return -EAGAIN;
+ }
+
+ /*
+ * Clear old maps. this also does some error checking for us
+ */
+ retval = do_munmap(addr, len);
+ if (retval != 0)
+ return retval;
+
+ /* Check against address space limits *after* clearing old maps... */
+ if ((mm->total_vm << PAGE_SHIFT) + len
+ > current->rlim[RLIMIT_AS].rlim_cur)
+ return -ENOMEM;
+
+ if (mm->map_count > MAX_MAP_COUNT)
+ return -ENOMEM;
+
+ if (!vm_enough_memory(len >> PAGE_SHIFT))
+ return -ENOMEM;
+
+ /*
+ * create a vma struct for an anonymous mapping
+ */
+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!vma)
+ return -ENOMEM;
+
+ vma->vm_mm = mm;
+ vma->vm_start = addr;
+ vma->vm_end = addr + len;
+ vma->vm_flags = vm_flags(PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE) | mm->def_flags;
+
+ vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
+ vma->vm_ops = NULL;
+ vma->vm_offset = 0;
+ vma->vm_file = NULL;
+ vma->vm_pte = 0;
+
+ /*
+ * merge_segments may merge our vma, so we can't refer to it
+ * after the call. Save the values we need now ...
+ */
+ flags = vma->vm_flags;
+ addr = vma->vm_start;
+ insert_vm_struct(mm, vma);
+ merge_segments(mm, vma->vm_start, vma->vm_end);
+
+ mm->total_vm += len >> PAGE_SHIFT;
+ if (flags & VM_LOCKED) {
+ mm->locked_vm += len >> PAGE_SHIFT;
+ make_pages_present(addr, addr + len);
+ }
+ return addr;
X }
X
X /* Build the AVL tree corresponding to the VMA list. */
diff -u --recursive --new-file v2.3.5/linux/mm/mremap.c linux/mm/mremap.c
--- v2.3.5/linux/mm/mremap.c Sun Nov 22 09:38:19 1998
+++ linux/mm/mremap.c Thu Jun 3 23:15:29 1999
@@ -134,12 +134,14 @@
X new_vma->vm_start = new_addr;
X new_vma->vm_end = new_addr+new_len;
X new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start);
+ lock_kernel();
X if (new_vma->vm_file)
X new_vma->vm_file->f_count++;
X if (new_vma->vm_ops && new_vma->vm_ops->open)
X new_vma->vm_ops->open(new_vma);
X insert_vm_struct(current->mm, new_vma);
X merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end);
+ unlock_kernel();
X do_munmap(addr, old_len);
X current->mm->total_vm += new_len >> PAGE_SHIFT;
X if (new_vma->vm_flags & VM_LOCKED) {
@@ -166,7 +168,6 @@
X unsigned long ret = -EINVAL;


X
X down(&current->mm->mmap_sem);
- lock_kernel();

X if (addr & ~PAGE_MASK)
X goto out;
X old_len = PAGE_ALIGN(old_len);
@@ -239,7 +240,6 @@
X else
X ret = -ENOMEM;


X out:
- unlock_kernel();
X up(&current->mm->mmap_sem);

X return ret;
X }
diff -u --recursive --new-file v2.3.5/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.5/linux/mm/swapfile.c Mon May 31 22:28:07 1999
+++ linux/mm/swapfile.c Mon Jun 7 16:20:36 1999
@@ -5,6 +5,7 @@
X * Swap reorganised 29.12.95, Stephen Tweedie
X */
X
+#include <linux/config.h>
X #include <linux/malloc.h>
X #include <linux/smp_lock.h>
X #include <linux/kernel_stat.h>
@@ -573,7 +574,7 @@
X } else if (S_ISREG(swap_dentry->d_inode->i_mode)) {
X error = -EBUSY;
X for (i = 0 ; i < nr_swapfiles ; i++) {
- if (i == type)
+ if (i == type || !swap_info[i].swap_file)
X continue;
X if (swap_dentry->d_inode == swap_info[i].swap_file->d_inode)
X goto bad_swap;
diff -u --recursive --new-file v2.3.5/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.5/linux/net/core/dev.c Wed Jun 2 14:44:39 1999
+++ linux/net/core/dev.c Wed Jun 9 14:45:36 1999
@@ -263,13 +263,13 @@
X {
X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev != NULL; dev = dev->next) {
X if (strcmp(dev->name, name) == 0)
X goto out;
X }
X out:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X return dev;
X }
X
@@ -277,13 +277,13 @@
X {
X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev != NULL; dev = dev->next) {
X if (dev->ifindex == ifindex)
X goto out;
X }
X out:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X return dev;
X }
X
@@ -291,14 +291,14 @@
X {
X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev != NULL; dev = dev->next) {
X if (dev->type == type &&
X memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
X goto out;
X }
X out:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X return dev;
X }
X

@@ -321,7 +321,7 @@
X }

X return -ENFILE; /* Over 100 of the things .. bail out! */
X }
-
+
X struct device *dev_alloc(const char *name, int *err)
X {
X struct device *dev=kmalloc(sizeof(struct device)+16, GFP_KERNEL);
@@ -387,9 +387,6 @@
X if (dev->flags&IFF_UP)
X return 0;
X
- /* Setup the lock before we open the faucet. */
- spin_lock_init(&dev->xmit_lock);
-
X /*
X * Call device private open method
X */
@@ -452,10 +449,10 @@
X if (dev) {
X dev_do_clear_fastroute(dev);
X } else {
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev; dev = dev->next)
X dev_do_clear_fastroute(dev);
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X }
X }
X #endif
@@ -596,59 +593,61 @@
X struct device *dev = skb->dev;
X struct Qdisc *q;
X
-#ifdef CONFIG_NET_PROFILE
- start_bh_atomic();
- NET_PROFILE_ENTER(dev_queue_xmit);
-#endif
-
- spin_lock_bh(&dev->xmit_lock);
+ /* Grab device queue */
+ spin_lock_bh(&dev->queue_lock);
X q = dev->qdisc;
X if (q->enqueue) {
X q->enqueue(skb, q);
- qdisc_wakeup(dev);
- spin_unlock_bh(&dev->xmit_lock);
X
-#ifdef CONFIG_NET_PROFILE
- NET_PROFILE_LEAVE(dev_queue_xmit);
- end_bh_atomic();
-#endif
+ /* If the device is not busy, kick it.
+ * Otherwise or if queue is not empty after kick,
+ * add it to run list.
+ */
+ if (dev->tbusy || qdisc_restart(dev))
+ qdisc_run(dev->qdisc);
X
+ spin_unlock_bh(&dev->queue_lock);
X return 0;
X }
+ spin_unlock_bh(&dev->queue_lock);
X
X /* The device has no queue. Common case for software devices:
X loopback, all the sorts of tunnels...
X
- Really, it is unlikely that bh protection is necessary here:
- virtual devices do not generate EOI events.
- However, it is possible, that they rely on bh protection
+ Really, it is unlikely that xmit_lock protection is necessary here.
+ (f.e. loopback and IP tunnels are clean ignoring statistics counters.)
+ However, it is possible, that they rely on protection
X made by us here.
+
+ Check this and shot the lock. It is not prone from deadlocks.
+ Either shot noqueue qdisc, it is even simpler 8)
X */
X if (dev->flags&IFF_UP) {
X if (netdev_nit)
X dev_queue_xmit_nit(skb,dev);
- if (dev->hard_start_xmit(skb, dev) == 0) {
- spin_unlock_bh(&dev->xmit_lock);
-
-#ifdef CONFIG_NET_PROFILE
- NET_PROFILE_LEAVE(dev_queue_xmit);
- end_bh_atomic();
-#endif
X
- return 0;
+ local_bh_disable();
+ if (dev->xmit_lock_owner != smp_processor_id()) {
+ spin_lock(&dev->xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
+ if (dev->hard_start_xmit(skb, dev) == 0) {
+ dev->xmit_lock_owner = -1;
+ spin_unlock_bh(&dev->xmit_lock);
+ return 0;
+ }
+ dev->xmit_lock_owner = -1;
+ spin_unlock_bh(&dev->xmit_lock);
+ if (net_ratelimit())
+ printk(KERN_DEBUG "Virtual device %s asks to queue packet!\n", dev->name);
+ } else {
+ /* Recursion is detected! It is possible, unfortunately */
+ local_bh_enable();
+ if (net_ratelimit())
+ printk(KERN_DEBUG "Dead loop on virtual device %s, fix it urgently!\n", dev->name);
X }
- if (net_ratelimit())
- printk(KERN_DEBUG "Virtual device %s asks to queue packet!\n", dev->name);
X }
- spin_unlock_bh(&dev->xmit_lock);
X
X kfree_skb(skb);
-
-#ifdef CONFIG_NET_PROFILE
- NET_PROFILE_LEAVE(dev_queue_xmit);
- end_bh_atomic();
-#endif
-


X return 0;
X }
X

@@ -660,9 +659,6 @@
X int netdev_dropping = 0;
X int netdev_max_backlog = 300;
X atomic_t netdev_rx_dropped;
-#ifdef CONFIG_CPU_IS_SLOW
-int net_cpu_congestion;
-#endif
X
X #ifdef CONFIG_NET_HW_FLOWCONTROL
X int netdev_throttle_events;
@@ -852,14 +848,6 @@
X struct packet_type *pt_prev;
X unsigned short type;
X unsigned long start_time = jiffies;
-#ifdef CONFIG_CPU_IS_SLOW
- static unsigned long start_busy = 0;
- static unsigned long ave_busy = 0;
-
- if (start_busy == 0)
- start_busy = start_time;
- net_cpu_congestion = ave_busy>>8;
-#endif
X
X NET_PROFILE_ENTER(net_bh);
X /*
@@ -869,9 +857,9 @@
X * latency on a transmit interrupt bh.
X */
X
- if (qdisc_head.forw != &qdisc_head)
+ if (qdisc_pending())
X qdisc_run_queues();
-
+
X /*
X * Any data left to process. This may occur because a
X * mark_bh() is done after we empty the queue including
@@ -899,19 +887,6 @@
X */
X skb = skb_dequeue(&backlog);
X
-#ifdef CONFIG_CPU_IS_SLOW
- if (ave_busy > 128*16) {
- kfree_skb(skb);
- while ((skb = skb_dequeue(&backlog)) != NULL)
- kfree_skb(skb);
- break;
- }
-#endif
-
-
-#if 0
- NET_PROFILE_SKB_PASSED(skb, net_bh_skb);
-#endif
X #ifdef CONFIG_NET_FASTROUTE
X if (skb->pkt_type == PACKET_FASTROUTE) {
X dev_queue_xmit(skb);
@@ -1022,16 +997,9 @@
X * One last output flush.
X */
X
- if (qdisc_head.forw != &qdisc_head)
+ if (qdisc_pending())
X qdisc_run_queues();
X
-#ifdef CONFIG_CPU_IS_SLOW
- if (1) {
- unsigned long start_idle = jiffies;
- ave_busy += ((start_idle - start_busy)<<3) - (ave_busy>>4);
- start_busy = 0;
- }
-#endif
X #ifdef CONFIG_NET_HW_FLOWCONTROL
X if (netdev_dropping)
X netdev_wakeup();
@@ -1065,14 +1033,6 @@
X */
X
X /*
- * This call is useful, but I'd remove it too.
- *
- * The reason is purely aestetical, it is the only call
- * from SIOC* family using struct ifreq in reversed manner.
- * Besides that, it is pretty silly to put "drawing" facility
- * to kernel, it is useful only to print ifindices
- * in readable form, is not it? --ANK
- *
X * We need this ioctl for efficient implementation of the
X * if_indextoname() function required by the IPv6 API. Without
X * it, we would have to search all the interfaces to find a
@@ -1138,7 +1098,7 @@
X */
X
X total = 0;
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev != NULL; dev = dev->next) {
X for (i=0; i<NPROTO; i++) {
X if (gifconf_list[i]) {
@@ -1152,7 +1112,7 @@
X }
X }
X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X
X if(pos != NULL) {
X int err = copy_to_user(ifc.ifc_buf, pos, total);
@@ -1232,7 +1192,7 @@
X len+=size;
X
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev != NULL; dev = dev->next) {
X size = sprintf_stats(buffer+len, dev);
X len+=size;
@@ -1245,7 +1205,7 @@
X if(pos>offset+length)
X break;
X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X
X *start=buffer+(offset-begin); /* Start of wanted data */
X len-=(offset-begin); /* Start slop */
@@ -1347,7 +1307,7 @@
X pos+=size;
X len+=size;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for(dev = dev_base; dev != NULL; dev = dev->next) {
X size = sprintf_wireless_stats(buffer+len, dev);
X len+=size;
@@ -1360,7 +1320,7 @@
X if(pos > offset + length)
X break;
X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X
X *start = buffer + (offset - begin); /* Start of wanted data */
X len -= (offset - begin); /* Start slop */
@@ -1736,11 +1696,10 @@
X if (IW_IS_SET(cmd)) {
X if (!suser())
X return -EPERM;
- rtnl_lock();
X }
+ rtnl_lock();
X ret = dev_ifsioc(&ifr, cmd);
- if (IW_IS_SET(cmd))
- rtnl_unlock();
+ rtnl_unlock();
X if (!ret && IW_IS_GET(cmd) &&
X copy_to_user(arg, &ifr, sizeof(struct ifreq)))
X return -EFAULT;
@@ -1769,6 +1728,10 @@
X {
X struct device *d, **dp;
X
+ spin_lock_init(&dev->queue_lock);
+ spin_lock_init(&dev->xmit_lock);
+ dev->xmit_lock_owner = -1;
+
X if (dev_boot_phase) {
X /* This is NOT bug, but I am not sure, that all the
X devices, initialized before netdev module is started
@@ -1784,14 +1747,13 @@
X printk(KERN_INFO "early initialization of device %s is deferred\n", dev->name);
X
X /* Check for existence, and append to tail of chain */
- write_lock_bh(&dev_base_lock);
X for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
X if (d == dev || strcmp(d->name, dev->name) == 0) {
- write_unlock_bh(&dev_base_lock);
X return -EEXIST;
X }
X }
X dev->next = NULL;
+ write_lock_bh(&dev_base_lock);
X *dp = dev;
X write_unlock_bh(&dev_base_lock);
X return 0;
@@ -1803,24 +1765,22 @@
X if (dev->init && dev->init(dev) != 0)
X return -EIO;
X
+ dev->ifindex = dev_new_index();
+ if (dev->iflink == -1)
+ dev->iflink = dev->ifindex;
+
X /* Check for existence, and append to tail of chain */
- write_lock_bh(&dev_base_lock);
X for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
X if (d == dev || strcmp(d->name, dev->name) == 0) {
- write_unlock_bh(&dev_base_lock);
X return -EEXIST;
X }
X }
X dev->next = NULL;
X dev_init_scheduler(dev);
+ write_lock_bh(&dev_base_lock);
X *dp = dev;
X write_unlock_bh(&dev_base_lock);
X
- dev->ifindex = -1;
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
-
X /* Notify protocols, that a new device appeared. */
X notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
X
@@ -1831,15 +1791,35 @@
X {
X struct device *d, **dp;
X
- if (dev_boot_phase == 0) {
- /* If device is running, close it.
- It is very bad idea, really we should
- complain loudly here, but random hackery
- in linux/drivers/net likes it.
- */
- if (dev->flags & IFF_UP)
- dev_close(dev);
+ /* If device is running, close it first. */
+ if (dev->flags & IFF_UP)
+ dev_close(dev);
X
+ /* And unlink it from device chain. */
+ for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
+ if (d == dev) {
+ write_lock_bh(&dev_base_lock);
+ *dp = d->next;
+ write_unlock_bh(&dev_base_lock);
+
+ /* Sorry. It is known "feature". The race is clear.
+ Keep it after device reference counting will
+ be complete.
+ */
+ synchronize_bh();
+ break;
+ }
+ }
+ if (d == NULL)
+ return -ENODEV;
+
+ /* It is "synchronize_bh" to those of guys, who overslept
+ in skb_alloc/page fault etc. that device is off-line.
+ Again, it can be removed only if devices are refcounted.
+ */
+ dev_lock_wait();
+
+ if (dev_boot_phase == 0) {
X #ifdef CONFIG_NET_FASTROUTE
X dev_clear_fastroute(dev);
X #endif
@@ -1856,27 +1836,11 @@
X * Flush the multicast chain
X */
X dev_mc_discard(dev);
-
- /* To avoid pointers looking to nowhere,
- we wait for end of critical section */
- dev_lock_wait();
X }
X
- /* And unlink it from device chain. */
- write_lock_bh(&dev_base_lock);
- for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev) {
- *dp = d->next;
- d->next = NULL;
- write_unlock_bh(&dev_base_lock);
-
- if (dev->destructor)
- dev->destructor(dev);


- return 0;
- }
- }

- write_unlock_bh(&dev_base_lock);
- return -ENODEV;
+ if (dev->destructor)
+ dev->destructor(dev);


+ return 0;
X }
X
X

@@ -2018,16 +1982,24 @@
X * If the call to dev->init fails, the dev is removed
X * from the chain disconnecting the device until the
X * next reboot.
+ *
+ * NB At boot phase networking is dead. No locking is required.
+ * But we still preserve dev_base_lock for sanity.
X */
X
X dp = &dev_base;
X while ((dev = *dp) != NULL) {
+ spin_lock_init(&dev->queue_lock);
+ spin_lock_init(&dev->xmit_lock);
+ dev->xmit_lock_owner = -1;
X dev->iflink = -1;
X if (dev->init && dev->init(dev)) {
X /*
X * It failed to come up. Unhook it.
X */
+ write_lock_bh(&dev_base_lock);
X *dp = dev->next;
+ write_unlock_bh(&dev_base_lock);
X } else {
X dp = &dev->next;
X dev->ifindex = dev_new_index();
@@ -2055,6 +2027,7 @@
X
X dev_boot_phase = 0;
X
+ dst_init();
X dev_mcast_init();
X
X #ifdef CONFIG_IP_PNP
diff -u --recursive --new-file v2.3.5/linux/net/core/dev_mcast.c linux/net/core/dev_mcast.c
--- v2.3.5/linux/net/core/dev_mcast.c Mon May 31 22:28:07 1999
+++ linux/net/core/dev_mcast.c Wed Jun 9 14:45:36 1999
@@ -58,7 +58,11 @@
X *
X * Device mc lists are changed by bh at least if IPv6 is enabled,
X * so that it must be bh protected.
+ *
+ * We protect all mc lists with global rw lock
+ * and block accesses to device mc filters with dev->xmit_lock.
X */
+static rwlock_t dev_mc_lock = RW_LOCK_UNLOCKED;
X
X /*
X * Update the multicast list into the physical NIC controller.
@@ -69,7 +73,7 @@
X /* Don't do anything till we up the interface
X [dev_open will call this function so the list will
X stay sane] */
-
+
X if(!(dev->flags&IFF_UP))
X return;
X
@@ -80,11 +84,15 @@
X if(dev->set_multicast_list==NULL)
X return;
X
- start_bh_atomic();
+ read_lock_bh(&dev_mc_lock);
+ spin_lock(&dev->xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
X dev->set_multicast_list(dev);
- end_bh_atomic();
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
+ read_unlock_bh(&dev_mc_lock);
X }
-
+
X /*
X * Delete a device level multicast
X */
@@ -94,7 +102,7 @@
X int err = 0;
X struct dev_mc_list *dmi, **dmip;
X
- start_bh_atomic();
+ write_lock_bh(&dev_mc_lock);
X for (dmip=&dev->mc_list; (dmi=*dmip)!=NULL; dmip=&dmi->next) {
X /*
X * Find the entry we want to delete. The device could
@@ -120,14 +128,15 @@
X * We have altered the list, so the card
X * loaded filter is now wrong. Fix it
X */
- end_bh_atomic();
+ write_unlock_bh(&dev_mc_lock);
+
X dev_mc_upload(dev);


X return 0;
X }
X }

X err = -ENOENT;
X done:
- end_bh_atomic();
+ write_unlock_bh(&dev_mc_lock);


X return err;
X }
X

@@ -140,9 +149,12 @@
X int err = 0;
X struct dev_mc_list *dmi, *dmi1;
X
+ /* RED-PEN: does gfp_any() work now? It requires
+ true local_bh_disable rather than global.
+ */
X dmi1 = (struct dev_mc_list *)kmalloc(sizeof(*dmi), gfp_any());
X
- start_bh_atomic();
+ write_lock_bh(&dev_mc_lock);
X for(dmi=dev->mc_list; dmi!=NULL; dmi=dmi->next) {
X if (memcmp(dmi->dmi_addr,addr,dmi->dmi_addrlen)==0 && dmi->dmi_addrlen==alen) {
X if (glbl) {


@@ -156,8 +168,10 @@
X }

X }
X
- if ((dmi=dmi1)==NULL)
+ if ((dmi=dmi1)==NULL) {
+ write_unlock_bh(&dev_mc_lock);
X return -ENOMEM;
+ }
X memcpy(dmi->dmi_addr, addr, alen);
X dmi->dmi_addrlen=alen;
X dmi->next=dev->mc_list;
@@ -165,12 +179,12 @@
X dmi->dmi_gusers=glbl ? 1 : 0;
X dev->mc_list=dmi;
X dev->mc_count++;
- end_bh_atomic();
+ write_unlock_bh(&dev_mc_lock);
X dev_mc_upload(dev);
X return 0;
X
X done:
- end_bh_atomic();
+ write_unlock_bh(&dev_mc_lock);
X if (dmi1)
X kfree(dmi1);
X return err;
@@ -182,7 +196,7 @@
X
X void dev_mc_discard(struct device *dev)
X {
- start_bh_atomic();
+ write_lock_bh(&dev_mc_lock);
X while (dev->mc_list!=NULL) {
X struct dev_mc_list *tmp=dev->mc_list;
X dev->mc_list=tmp->next;
@@ -191,7 +205,7 @@
X kfree_s(tmp,sizeof(*tmp));
X }
X dev->mc_count=0;
- end_bh_atomic();
+ write_unlock_bh(&dev_mc_lock);
X }
X
X #ifdef CONFIG_PROC_FS
@@ -203,8 +217,9 @@
X int len=0;
X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev; dev = dev->next) {
+ read_lock_bh(&dev_mc_lock);
X for (m = dev->mc_list; m; m = m->next) {
X int i;
X
@@ -221,14 +236,17 @@
X len=0;
X begin=pos;
X }
- if (pos > offset+length)
+ if (pos > offset+length) {
+ read_unlock_bh(&dev_mc_lock);
X goto done;
+ }
X }
+ read_unlock_bh(&dev_mc_lock);
X }
X *eof = 1;
X
X done:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X *start=buffer+(offset-begin);
X len-=(offset-begin);
X if(len>length)
diff -u --recursive --new-file v2.3.5/linux/net/core/dst.c linux/net/core/dst.c
--- v2.3.5/linux/net/core/dst.c Mon May 31 22:28:07 1999
+++ linux/net/core/dst.c Wed Jun 9 14:45:36 1999
@@ -16,6 +16,7 @@
X #include <linux/errno.h>
X #include <linux/netdevice.h>
X #include <linux/skbuff.h>
+#include <linux/init.h>
X
X #include <net/dst.h>
X
@@ -39,16 +40,16 @@
X static struct timer_list dst_gc_timer =
X { NULL, NULL, DST_GC_MIN, 0L, dst_run_gc };
X
-#if RT_CACHE_DEBUG >= 2
-atomic_t hh_count;
-#endif
X
X static void dst_run_gc(unsigned long dummy)
X {
X int delayed = 0;
X struct dst_entry * dst, **dstp;
X
- spin_lock(&dst_lock);
+ if (!spin_trylock(&dst_lock)) {
+ mod_timer(&dst_gc_timer, jiffies + HZ/10);
+ return;
+ }
X
X del_timer(&dst_gc_timer);
X dstp = &dst_garbage_list;
@@ -159,4 +160,37 @@
X dst->ops->destroy(dst);
X atomic_dec(&dst_total);
X kfree(dst);
+}
+
+static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct device *dev = ptr;
+ struct dst_entry *dst;
+
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ case NETDEV_DOWN:
+ spin_lock_bh(&dst_lock);
+ for (dst = dst_garbage_list; dst; dst = dst->next) {
+ if (dst->dev == dev) {
+ dst->input = dst_discard;
+ dst->output = dst_blackhole;
+ dst->dev = &loopback_dev;
+ }
+ }
+ spin_unlock_bh(&dst_lock);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+struct notifier_block dst_dev_notifier = {
+ dst_dev_event,
+ NULL,
+ 0
+};
+
+__initfunc(void dst_init(void))
+{
+ register_netdevice_notifier(&dst_dev_notifier);
X }
diff -u --recursive --new-file v2.3.5/linux/net/core/neighbour.c linux/net/core/neighbour.c
--- v2.3.5/linux/net/core/neighbour.c Wed Jun 2 14:44:39 1999
+++ linux/net/core/neighbour.c Wed Jun 9 14:45:36 1999
@@ -12,12 +12,10 @@
X *
X * Fixes:
X * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
- * Horst von Brand Add #include <linux/string.h>


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

X #include <linux/types.h>
-#include <linux/string.h>
X #include <linux/kernel.h>
X #include <linux/socket.h>
X #include <linux/sched.h>
@@ -30,33 +28,6 @@
X #include <net/sock.h>
X #include <linux/rtnetlink.h>
X
-/*
- NOTE. The most unpleasent question is serialization of
- accesses to resolved addresses. The problem is that addresses
- are modified by bh, but they are referenced from normal
- kernel thread. Before today no locking was made.
- My reasoning was that corrupted address token will be copied
- to packet with cosmologically small probability
- (it is even difficult to estimate such small number)
- and it is very silly to waste cycles in fast path to lock them.
-
- But now I changed my mind, but not because previous statement
- is wrong. Actually, neigh->ha MAY BE not opaque byte array,
- but reference to some private data. In this case even neglibible
- corruption probability becomes bug.
-
- - hh cache is protected by rwlock. It assumes that
- hh cache update procedure is short and fast, and that
- read_lock is cheaper than start_bh_atomic().
- - ha tokens, saved in neighbour entries, are protected
- by bh_atomic().
- - no protection is made in /proc reading. It is OK, because
- /proc is broken by design in any case, and
- corrupted output is normal behaviour there.
-
- --ANK (981025)
- */
-
X #define NEIGH_DEBUG 1
X
X #define NEIGH_PRINTK(x...) printk(x)
@@ -83,6 +54,46 @@
X static int neigh_glbl_allocs;
X static struct neigh_table *neigh_tables;
X
+#if defined(__i386__) && defined(__SMP__)
+#define ASSERT_WL(n) if ((int)((n)->lock.lock) >= 0) { printk("WL assertion failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
+#else
+#define ASSERT_WL(n) do { } while(0)
+#endif
+
+/*
+ Neighbour hash table buckets are protected with rwlock tbl->lock.
+
+ - All the scans/updates to hash buckets MUST be made under this lock.
+ - NOTHING clever should be made under this lock: no callbacks
+ to protocol backends, no attempts to send something to network.
+ It will result in deadlocks, if backend/driver wants to use neighbour
+ cache.
+ - If the entry requires some non-trivial actions, increase
+ its reference count and release table lock.
+
+ Neighbour entries are protected:
+ - with reference count.
+ - with rwlock neigh->lock
+
+ Reference count prevents destruction.
+
+ neigh->lock mainly serializes ll address data and its validity state.
+ However, the same lock is used to protect another entry fields:
+ - timer
+ - resolution queue
+
+ Again, nothing clever shall be made under neigh->lock,
+ the most complicated procedure, which we allow is dev->hard_header.
+ It is supposed, that dev->hard_header is simplistic and does
+ not make callbacks to neighbour tables.
+
+ The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
+ list of neighbour tables. This list is used only in process context,
+ so that this lock is useless with big kernel lock.
+ */
+
+static rwlock_t neigh_tbl_lock = RW_LOCK_UNLOCKED;
+
X static int neigh_blackhole(struct sk_buff *skb)
X {
X kfree_skb(skb);
@@ -106,13 +117,11 @@
X int shrunk = 0;
X int i;
X
- if (atomic_read(&tbl->lock))
- return 0;
-
X for (i=0; i<=NEIGH_HASHMASK; i++) {
X struct neighbour *n, **np;
X
X np = &tbl->hash_buckets[i];
+ write_lock_bh(&tbl->lock);
X while ((n = *np) != NULL) {
X /* Neighbour record may be discarded if:
X - nobody refers to it.
@@ -124,6 +133,7 @@
X It is not clear, what is better table overflow
X or flooding.
X */
+ write_lock(&n->lock);
X if (atomic_read(&n->refcnt) == 0 &&
X !(n->nud_state&NUD_PERMANENT) &&
X (n->nud_state != NUD_INCOMPLETE ||
@@ -132,11 +142,14 @@
X n->tbl = NULL;
X tbl->entries--;
X shrunk = 1;
+ write_unlock(&n->lock);
X neigh_destroy(n);
X continue;
X }
+ write_unlock(&n->lock);
X np = &n->next;
X }
+ write_unlock_bh(&tbl->lock);
X }
X
X tbl->last_flush = jiffies;
@@ -147,12 +160,8 @@


X {
X int i;
X

- if (atomic_read(&tbl->lock)) {
- NEIGH_PRINTK1("neigh_ifdown: impossible event 1763\n");
- return -EBUSY;
- }
+ write_lock_bh(&tbl->lock);
X
- start_bh_atomic();
X for (i=0; i<=NEIGH_HASHMASK; i++) {
X struct neighbour *n, **np;
X
@@ -163,6 +172,7 @@
X continue;
X }
X *np = n->next;
+ write_lock(&n->lock);
X n->tbl = NULL;
X tbl->entries--;
X if (atomic_read(&n->refcnt)) {
@@ -185,33 +195,32 @@
X else
X n->nud_state = NUD_NONE;
X NEIGH_PRINTK2("neigh %p is stray.\n", n);
- } else
+ write_unlock(&n->lock);
+ } else {
+ write_unlock(&n->lock);
X neigh_destroy(n);
+ }
X }
X }
X
X del_timer(&tbl->proxy_timer);
X skb_queue_purge(&tbl->proxy_queue);
X pneigh_ifdown(tbl, dev);
- end_bh_atomic();
+ write_unlock_bh(&tbl->lock);


X return 0;
X }
X

-static struct neighbour *neigh_alloc(struct neigh_table *tbl, int creat)
+static struct neighbour *neigh_alloc(struct neigh_table *tbl)
X {
X struct neighbour *n;
X unsigned long now = jiffies;
X
- if (tbl->entries > tbl->gc_thresh1) {
- if (creat < 0)
+ if (tbl->entries > tbl->gc_thresh3 ||
+ (tbl->entries > tbl->gc_thresh2 &&
+ now - tbl->last_flush > 5*HZ)) {
+ if (neigh_forced_gc(tbl) == 0 &&
+ tbl->entries > tbl->gc_thresh3)
X return NULL;
- if (tbl->entries > tbl->gc_thresh3 ||
- (tbl->entries > tbl->gc_thresh2 &&
- now - tbl->last_flush > 5*HZ)) {
- if (neigh_forced_gc(tbl) == 0 &&
- tbl->entries > tbl->gc_thresh3)
- return NULL;
- }
X }
X
X n = kmalloc(tbl->entry_size, GFP_ATOMIC);
@@ -221,6 +230,7 @@
X memset(n, 0, tbl->entry_size);
X
X skb_queue_head_init(&n->arp_queue);
+ n->lock = RW_LOCK_UNLOCKED;
X n->updated = n->used = now;
X n->nud_state = NUD_NONE;
X n->output = neigh_blackhole;
@@ -233,9 +243,8 @@
X return n;
X }
X
-
-struct neighbour * __neigh_lookup(struct neigh_table *tbl, const void *pkey,
- struct device *dev, int creat)
+struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
+ struct device *dev)
X {
X struct neighbour *n;
X u32 hash_val;
@@ -247,17 +256,26 @@
X hash_val ^= hash_val>>3;
X hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
X
+ read_lock_bh(&tbl->lock);
X for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
X if (dev == n->dev &&
X memcmp(n->primary_key, pkey, key_len) == 0) {
X atomic_inc(&n->refcnt);
- return n;
+ break;
X }
X }
- if (!creat)
- return NULL;
+ read_unlock_bh(&tbl->lock);
+ return n;
+}
X
- n = neigh_alloc(tbl, creat);
+struct neighbour * neigh_create(struct neigh_table *tbl, const void *pkey,
+ struct device *dev)
+{
+ struct neighbour *n, *n1;
+ u32 hash_val;
+ int key_len = tbl->key_len;
+
+ n = neigh_alloc(tbl);
X if (n == NULL)
X return NULL;
X
@@ -277,11 +295,30 @@
X }
X
X n->confirmed = jiffies - (n->parms->base_reachable_time<<1);
- atomic_set(&n->refcnt, 1);
+
+ hash_val = *(u32*)(pkey + key_len - 4);
+ hash_val ^= (hash_val>>16);
+ hash_val ^= hash_val>>8;
+ hash_val ^= hash_val>>3;
+ hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
+
+ write_lock_bh(&tbl->lock);
+ for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
+ if (dev == n1->dev &&
+ memcmp(n1->primary_key, pkey, key_len) == 0) {
+ atomic_inc(&n1->refcnt);
+ write_unlock_bh(&tbl->lock);
+ neigh_destroy(n);
+ return n1;
+ }
+ }
+
X tbl->entries++;
+ n->tbl = tbl;
+ atomic_set(&n->refcnt, 1);
X n->next = tbl->hash_buckets[hash_val];
X tbl->hash_buckets[hash_val] = n;
- n->tbl = tbl;
+ write_unlock_bh(&tbl->lock);
X NEIGH_PRINTK2("neigh %p is created.\n", n);
X return n;
X }
@@ -393,7 +430,9 @@
X while ((hh = neigh->hh) != NULL) {
X neigh->hh = hh->hh_next;
X hh->hh_next = NULL;
+ write_lock_bh(&hh->hh_lock);
X hh->hh_output = neigh_blackhole;
+ write_unlock_bh(&hh->hh_lock);
X if (atomic_dec_and_test(&hh->hh_refcnt))
X kfree(hh);
X }
@@ -411,6 +450,8 @@
X
X /* Neighbour state is suspicious;
X disable fast path.
+
+ Called with write_locked neigh.
X */
X static void neigh_suspect(struct neighbour *neigh)
X {
@@ -418,6 +459,8 @@
X
X NEIGH_PRINTK2("neigh %p is suspecteded.\n", neigh);
X
+ ASSERT_WL(neigh);
+
X neigh->output = neigh->ops->output;
X
X for (hh = neigh->hh; hh; hh = hh->hh_next)
@@ -426,6 +469,8 @@
X
X /* Neighbour state is OK;
X enable fast path.
+
+ Called with write_locked neigh.
X */
X static void neigh_connect(struct neighbour *neigh)
X {
@@ -433,6 +478,8 @@
X
X NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
X
+ ASSERT_WL(neigh);
+
X neigh->output = neigh->ops->connected_output;
X
X for (hh = neigh->hh; hh; hh = hh->hh_next)
@@ -448,6 +495,8 @@
X
X If a routine wants to know TRUE entry state, it calls
X neigh_sync before checking state.
+
+ Called with write_locked neigh.
X */
X
X static void neigh_sync(struct neighbour *n)
@@ -455,6 +504,7 @@
X unsigned long now = jiffies;
X u8 state = n->nud_state;
X
+ ASSERT_WL(n);
X if (state&(NUD_NOARP|NUD_PERMANENT))
X return;
X if (state&NUD_REACHABLE) {
@@ -478,11 +528,8 @@
X unsigned long now = jiffies;
X int i;
X
- if (atomic_read(&tbl->lock)) {
- tbl->gc_timer.expires = now + 1*HZ;
- add_timer(&tbl->gc_timer);
- return;
- }
+
+ write_lock(&tbl->lock);
X
X /*
X * periodicly recompute ReachableTime from random function
@@ -500,10 +547,15 @@
X
X np = &tbl->hash_buckets[i];
X while ((n = *np) != NULL) {
- unsigned state = n->nud_state;
+ unsigned state;
+
+ write_lock(&n->lock);
X
- if (state&(NUD_PERMANENT|NUD_IN_TIMER))
+ state = n->nud_state;
+ if (state&(NUD_PERMANENT|NUD_IN_TIMER)) {
+ write_unlock(&n->lock);
X goto next_elt;
+ }
X
X if ((long)(n->used - n->confirmed) < 0)
X n->used = n->confirmed;
@@ -514,6 +566,7 @@
X n->tbl = NULL;
X n->next = NULL;
X tbl->entries--;
+ write_unlock(&n->lock);
X neigh_destroy(n);
X continue;
X }
@@ -523,6 +576,7 @@
X n->nud_state = NUD_STALE;
X neigh_suspect(n);
X }
+ write_unlock(&n->lock);
X
X next_elt:
X np = &n->next;
@@ -531,6 +585,7 @@
X
X tbl->gc_timer.expires = now + tbl->gc_interval;
X add_timer(&tbl->gc_timer);
+ write_unlock(&tbl->lock);
X }
X
X static __inline__ int neigh_max_probes(struct neighbour *n)
@@ -546,11 +601,17 @@
X {
X unsigned long now = jiffies;
X struct neighbour *neigh = (struct neighbour*)arg;
- unsigned state = neigh->nud_state;
+ unsigned state;
+ int notify = 0;
+
+ write_lock(&neigh->lock);
+ atomic_inc(&neigh->refcnt);
+
+ state = neigh->nud_state;
X
X if (!(state&NUD_IN_TIMER)) {
X NEIGH_PRINTK1("neigh: timer & !nud_in_timer\n");
- return;
+ goto out;
X }
X
X if ((state&NUD_VALID) &&
@@ -558,18 +619,19 @@
X neigh->nud_state = NUD_REACHABLE;
X NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
X neigh_connect(neigh);
- return;
+ goto out;
X }
X if (state == NUD_DELAY) {
X NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
X neigh->nud_state = NUD_PROBE;
- neigh->probes = 0;
+ atomic_set(&neigh->probes, 0);
X }
X
- if (neigh->probes >= neigh_max_probes(neigh)) {
+ if (atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
X struct sk_buff *skb;
X
X neigh->nud_state = NUD_FAILED;
+ notify = 1;
X neigh->tbl->stats.res_failed++;
X NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
X
@@ -578,44 +640,60 @@
X
X So that, we try to be accurate and avoid dead loop. --ANK
X */
- while(neigh->nud_state==NUD_FAILED && (skb=__skb_dequeue(&neigh->arp_queue)) != NULL)
+ while(neigh->nud_state==NUD_FAILED && (skb=__skb_dequeue(&neigh->arp_queue)) != NULL) {
+ write_unlock(&neigh->lock);
X neigh->ops->error_report(neigh, skb);
+ write_lock(&neigh->lock);
+ }
X skb_queue_purge(&neigh->arp_queue);
- return;
+ goto out;
X }
X
X neigh->timer.expires = now + neigh->parms->retrans_time;
X add_timer(&neigh->timer);
+ write_unlock(&neigh->lock);
X
X neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue));
- neigh->probes++;
+ atomic_inc(&neigh->probes);
+ neigh_release(neigh);
+ return;
+
+out:
+ write_unlock(&neigh->lock);
+#ifdef CONFIG_ARPD
+ if (notify && neigh->parms->app_probes)
+ neigh_app_notify(neigh);
+#endif
+ neigh_release(neigh);
X }
X
X int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
X {
- start_bh_atomic();
+ write_lock_bh(&neigh->lock);
X if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE))) {
X if (!(neigh->nud_state&(NUD_STALE|NUD_INCOMPLETE))) {
X if (neigh->tbl == NULL) {
X NEIGH_PRINTK2("neigh %p used after death.\n", neigh);
X if (skb)
X kfree_skb(skb);
- end_bh_atomic();
+ write_unlock_bh(&neigh->lock);
X return 1;
X }
X if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
- neigh->probes = neigh->parms->ucast_probes;
+ atomic_set(&neigh->probes, neigh->parms->ucast_probes);
X neigh->nud_state = NUD_INCOMPLETE;
X neigh->timer.expires = jiffies + neigh->parms->retrans_time;
X add_timer(&neigh->timer);
-
+ write_unlock_bh(&neigh->lock);
X neigh->ops->solicit(neigh, skb);
- neigh->probes++;
+ atomic_inc(&neigh->probes);
+ write_lock_bh(&neigh->lock);
X } else {
X neigh->nud_state = NUD_FAILED;
+ write_unlock_bh(&neigh->lock);
+
X if (skb)
X kfree_skb(skb);
- end_bh_atomic();
X return 1;
X }
X }
@@ -629,7 +707,7 @@
X }
X __skb_queue_head(&neigh->arp_queue, skb);
X }
- end_bh_atomic();
+ write_unlock_bh(&neigh->lock);
X return 1;
X }
X if (neigh->nud_state == NUD_STALE) {
@@ -639,7 +717,7 @@
X add_timer(&neigh->timer);
X }
X }
- end_bh_atomic();
+ write_unlock_bh(&neigh->lock);


X return 0;
X }
X

@@ -651,9 +729,9 @@
X
X if (update) {
X for (hh=neigh->hh; hh; hh=hh->hh_next) {
- write_lock_irq(&hh->hh_lock);
+ write_lock_bh(&hh->hh_lock);
X update(hh, neigh->dev, neigh->ha);
- write_unlock_irq(&hh->hh_lock);
+ write_unlock_bh(&hh->hh_lock);
X }
X }
X }
@@ -665,15 +743,23 @@
X -- new is new state.
X -- override==1 allows to override existing lladdr, if it is different.
X -- arp==0 means that the change is administrative.
+
+ Caller MUST hold reference count on the entry.
X */
X
X int neigh_update(struct neighbour *neigh, u8 *lladdr, u8 new, int override, int arp)
X {
- u8 old = neigh->nud_state;
+ u8 old;
+ int err;
+ int notify = 0;
X struct device *dev = neigh->dev;
X
+ write_lock_bh(&neigh->lock);
+ old = neigh->nud_state;
+
+ err = -EPERM;
X if (arp && (old&(NUD_NOARP|NUD_PERMANENT)))
- return -EPERM;
+ goto out;
X
X if (!(new&NUD_VALID)) {
X if (old&NUD_IN_TIMER)
@@ -681,7 +767,9 @@
X if (old&NUD_CONNECTED)
X neigh_suspect(neigh);
X neigh->nud_state = new;
- return 0;
+ err = 0;
+ notify = old&NUD_VALID;
+ goto out;
X }
X
X /* Compare new lladdr with cached one */
@@ -698,14 +786,15 @@
X if (memcmp(lladdr, neigh->ha, dev->addr_len) == 0)
X lladdr = neigh->ha;
X else if (!override)
- return -EPERM;
+ goto out;
X }
X } else {
X /* No address is supplied; if we know something,
X use it, otherwise discard the request.
X */
+ err = -EINVAL;
X if (!(old&NUD_VALID))
- return -EINVAL;
+ goto out;
X lladdr = neigh->ha;
X }
X
@@ -718,10 +807,11 @@
X /* If entry was valid and address is not changed,
X do not change entry state, if new one is STALE.
X */
+ err = 0;
X if (old&NUD_VALID) {
X if (lladdr == neigh->ha)
X if (new == old || (new == NUD_STALE && (old&NUD_CONNECTED)))
- return 0;
+ goto out;
X }
X if (old&NUD_IN_TIMER)
X del_timer(&neigh->timer);
@@ -731,12 +821,11 @@
X neigh_update_hhs(neigh);
X neigh->confirmed = jiffies - (neigh->parms->base_reachable_time<<1);
X #ifdef CONFIG_ARPD
- if (neigh->parms->app_probes)
- neigh_app_notify(neigh);
+ notify = 1;
X #endif
X }
X if (new == old)
- return 0;
+ goto out;
X if (new&NUD_CONNECTED)
X neigh_connect(neigh);
X else
@@ -749,14 +838,22 @@
X while (neigh->nud_state&NUD_VALID &&
X (skb=__skb_dequeue(&neigh->arp_queue)) != NULL) {
X struct neighbour *n1 = neigh;
+ write_unlock_bh(&neigh->lock);
X /* On shaper/eql skb->dst->neighbour != neigh :( */
X if (skb->dst && skb->dst->neighbour)
X n1 = skb->dst->neighbour;
X n1->output(skb);
+ write_lock_bh(&neigh->lock);
X }
X skb_queue_purge(&neigh->arp_queue);
X }
- return 0;
+out:
+ write_unlock_bh(&neigh->lock);
+#ifdef CONFIG_ARPD


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

echo 'End of part 22'
echo 'File patch-2.3.6 is continued in part 23'
echo 23 > _shar_seq_.tmp

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part23

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


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

if test "$Scheck" != 23; then


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

+ if (notify && neigh->parms->app_probes)
+ neigh_app_notify(neigh);
+#endif

+ return err;
X }
X
X struct neighbour * neigh_event_ns(struct neigh_table *tbl,
@@ -839,15 +936,15 @@
X int err;


X struct device *dev = neigh->dev;

X if (dev->hard_header_cache && dst->hh == NULL) {


- start_bh_atomic();
+ write_lock_bh(&neigh->lock);

X if (dst->hh == NULL)
X neigh_hh_init(neigh, dst, dst->ops->protocol);
X err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len);


- end_bh_atomic();
+ write_unlock_bh(&neigh->lock);

X } else {
- start_bh_atomic();
+ read_lock_bh(&neigh->lock);
X err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len);
- end_bh_atomic();
+ read_unlock_bh(&neigh->lock);
X }
X if (err >= 0)
X return neigh->ops->queue_xmit(skb);
@@ -873,9 +970,9 @@
X
X __skb_pull(skb, skb->nh.raw - skb->data);
X
- start_bh_atomic();
+ read_lock_bh(&neigh->lock);
X err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len);
- end_bh_atomic();
+ read_unlock_bh(&neigh->lock);
X if (err >= 0)
X return neigh->ops->queue_xmit(skb);
X kfree_skb(skb);
@@ -949,8 +1046,10 @@


X return NULL;
X }
X }

+ write_lock_bh(&tbl->lock);
X p->next = tbl->parms.next;
X tbl->parms.next = p;
+ write_unlock_bh(&tbl->lock);
X }
X return p;
X }
@@ -961,10 +1060,11 @@
X
X if (parms == NULL || parms == &tbl->parms)
X return;
+ write_lock_bh(&tbl->lock);
X for (p = &tbl->parms.next; *p; p = &(*p)->next) {
X if (*p == parms) {
X *p = parms->next;
- synchronize_bh();
+ write_unlock_bh(&tbl->lock);
X #ifdef CONFIG_SYSCTL
X neigh_sysctl_unregister(parms);
X #endif
@@ -972,6 +1072,7 @@
X return;
X }
X }
+ write_unlock_bh(&tbl->lock);
X NEIGH_PRINTK1("neigh_release_parms: not found\n");
X }
X
@@ -983,6 +1084,7 @@
X tbl->parms.reachable_time = neigh_rand_reach_time(tbl->parms.base_reachable_time);
X
X init_timer(&tbl->gc_timer);
+ tbl->lock = RW_LOCK_UNLOCKED;
X tbl->gc_timer.data = (unsigned long)tbl;
X tbl->gc_timer.function = neigh_periodic_timer;
X tbl->gc_timer.expires = now + tbl->gc_interval + tbl->parms.reachable_time;
@@ -995,29 +1097,30 @@
X
X tbl->last_flush = now;
X tbl->last_rand = now + tbl->parms.reachable_time*20;
+ write_lock(&neigh_tbl_lock);
X tbl->next = neigh_tables;
X neigh_tables = tbl;
+ write_unlock(&neigh_tbl_lock);
X }
X
X int neigh_table_clear(struct neigh_table *tbl)
X {
X struct neigh_table **tp;
X
- start_bh_atomic();
X del_timer(&tbl->gc_timer);


X del_timer(&tbl->proxy_timer);
X skb_queue_purge(&tbl->proxy_queue);

X neigh_ifdown(tbl, NULL);
- end_bh_atomic();
X if (tbl->entries)
X printk(KERN_CRIT "neighbour leakage\n");
+ write_lock(&neigh_tbl_lock);
X for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
X if (*tp == tbl) {
X *tp = tbl->next;
- synchronize_bh();
X break;
X }
X }
+ write_unlock(&neigh_tbl_lock);
X #ifdef CONFIG_SYSCTL
X neigh_sysctl_unregister(&tbl->parms);
X #endif
@@ -1039,12 +1142,14 @@
X return -ENODEV;
X }
X
+ read_lock(&neigh_tbl_lock);
X for (tbl=neigh_tables; tbl; tbl = tbl->next) {


X int err = 0;

X struct neighbour *n;
X
X if (tbl->family != ndm->ndm_family)
X continue;
+ read_unlock(&neigh_tbl_lock);
X
X if (nda[NDA_DST-1] == NULL ||
X nda[NDA_DST-1]->rta_len != RTA_LENGTH(tbl->key_len))
@@ -1056,15 +1161,14 @@
X if (dev == NULL)
X return -EINVAL;
X
- start_bh_atomic();
- n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 0);
+ n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
X if (n) {
X err = neigh_update(n, NULL, NUD_FAILED, 1, 0);
X neigh_release(n);
X }
- end_bh_atomic();
X return err;
X }
+ read_unlock(&neigh_tbl_lock);
X
X return -EADDRNOTAVAIL;
X }
@@ -1081,12 +1185,15 @@
X return -ENODEV;
X }
X
+ read_lock(&neigh_tbl_lock);
X for (tbl=neigh_tables; tbl; tbl = tbl->next) {


X int err = 0;

X struct neighbour *n;
X
X if (tbl->family != ndm->ndm_family)
X continue;
+ read_unlock(&neigh_tbl_lock);
+
X if (nda[NDA_DST-1] == NULL ||
X nda[NDA_DST-1]->rta_len != RTA_LENGTH(tbl->key_len))
X return -EINVAL;
@@ -1100,8 +1207,7 @@
X if (nda[NDA_LLADDR-1] != NULL &&
X nda[NDA_LLADDR-1]->rta_len != RTA_LENGTH(dev->addr_len))
X return -EINVAL;
- start_bh_atomic();
- n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 0);
+ n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
X if (n) {
X if (nlh->nlmsg_flags&NLM_F_EXCL)
X err = -EEXIST;
@@ -1119,9 +1225,9 @@
X }
X if (n)
X neigh_release(n);
- end_bh_atomic();
X return err;
X }
+ read_unlock(&neigh_tbl_lock);
X
X return -EADDRNOTAVAIL;
X }
@@ -1141,15 +1247,17 @@
X ndm->ndm_family = n->ops->family;
X ndm->ndm_flags = n->flags;
X ndm->ndm_type = n->type;
- ndm->ndm_state = n->nud_state;
X ndm->ndm_ifindex = n->dev->ifindex;
X RTA_PUT(skb, NDA_DST, n->tbl->key_len, n->primary_key);
+ read_lock_bh(&n->lock);
+ ndm->ndm_state = n->nud_state;
X if (n->nud_state&NUD_VALID)
X RTA_PUT(skb, NDA_LLADDR, n->dev->addr_len, n->ha);
X ci.ndm_used = now - n->used;
X ci.ndm_confirmed = now - n->confirmed;
X ci.ndm_updated = now - n->updated;
X ci.ndm_refcnt = atomic_read(&n->refcnt);
+ read_unlock_bh(&n->lock);
X RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
X nlh->nlmsg_len = skb->tail - b;
X return skb->len;
@@ -1173,20 +1281,20 @@
X if (h < s_h) continue;
X if (h > s_h)
X s_idx = 0;
- start_bh_atomic();
+ read_lock_bh(&tbl->lock);
X for (n = tbl->hash_buckets[h], idx = 0; n;
X n = n->next, idx++) {
X if (idx < s_idx)
X continue;
X if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
X cb->nlh->nlmsg_seq, RTM_NEWNEIGH) <= 0) {
- end_bh_atomic();
+ read_unlock_bh(&tbl->lock);
X cb->args[1] = h;
X cb->args[2] = idx;
X return -1;
X }
X }
- end_bh_atomic();
+ read_unlock_bh(&tbl->lock);
X }
X
X cb->args[1] = h;
@@ -1203,6 +1311,7 @@
X
X s_t = cb->args[0];
X
+ read_lock(&neigh_tbl_lock);
X for (tbl=neigh_tables, t=0; tbl; tbl = tbl->next, t++) {
X if (t < s_t) continue;
X if (family && tbl->family != family)
@@ -1212,6 +1321,7 @@
X if (neigh_dump_table(tbl, skb, cb) < 0)
X break;
X }
+ read_unlock(&neigh_tbl_lock);
X
X cb->args[0] = t;
X
diff -u --recursive --new-file v2.3.5/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c
--- v2.3.5/linux/net/core/rtnetlink.c Mon May 31 22:28:07 1999
+++ linux/net/core/rtnetlink.c Wed Jun 9 14:45:36 1999
@@ -50,22 +50,22 @@
X #include <net/sock.h>
X #include <net/pkt_sched.h>
X
-atomic_t rtnl_rlockct;
-DECLARE_WAIT_QUEUE_HEAD(rtnl_wait);
+DECLARE_MUTEX(rtnl_sem);
X
-
-void rtnl_lock()
+void rtnl_lock(void)
X {
X rtnl_shlock();
X rtnl_exlock();
X }
-
-void rtnl_unlock()
+
+void rtnl_unlock(void)
X {
X rtnl_exunlock();
X rtnl_shunlock();
X }
X
+
+
X int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
X {
X memset(tb, 0, sizeof(struct rtattr*)*maxattr);
@@ -82,8 +82,6 @@
X #ifdef CONFIG_RTNETLINK
X struct sock *rtnl;
X
-unsigned long rtnl_wlockct;
-
X struct rtnetlink_link * rtnetlink_links[NPROTO];
X
X #define _S 1 /* superuser privileges required */
@@ -189,14 +187,14 @@
X int s_idx = cb->args[0];


X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);

X for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
X if (idx < s_idx)
X continue;
X if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq) <= 0)


X break;
X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);

X cb->args[0] = idx;
X
X return skb->len;
@@ -218,9 +216,7 @@
X continue;
X if (idx > s_idx)
X memset(&cb->args[0], 0, sizeof(cb->args));
- if (rtnetlink_links[idx][type].dumpit(skb, cb) == 0)
- continue;
- if (skb_tailroom(skb) < 256)
+ if (rtnetlink_links[idx][type].dumpit(skb, cb))
X break;
X }
X cb->family = idx;


@@ -247,8 +243,6 @@
X

X static int rtnetlink_done(struct netlink_callback *cb)
X {
- if (cap_raised(NETLINK_CB(cb->skb).eff_cap, CAP_NET_ADMIN) && cb->nlh->nlmsg_flags&NLM_F_ATOMIC)
- rtnl_shunlock();


X return 0;
X }
X

@@ -316,15 +310,9 @@
X if (link->dumpit == NULL)
X goto err_inval;
X
- /* Super-user locks all the tables to get atomic snapshot */
- if (cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)
- && nlh->nlmsg_flags&NLM_F_ATOMIC)
- atomic_inc(&rtnl_rlockct);
X if ((*errp = netlink_dump_start(rtnl, skb, nlh,
X link->dumpit,
X rtnetlink_done)) != 0) {
- if (cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN) && nlh->nlmsg_flags&NLM_F_ATOMIC)
- atomic_dec(&rtnl_rlockct);
X return -1;
X }
X rlen = NLMSG_ALIGN(nlh->nlmsg_len);
diff -u --recursive --new-file v2.3.5/linux/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- v2.3.5/linux/net/decnet/dn_neigh.c Mon May 31 22:28:07 1999
+++ linux/net/decnet/dn_neigh.c Wed Jun 9 14:45:36 1999
@@ -561,12 +561,13 @@
X
X len += sprintf(buffer + len, "Addr Flags State Use Blksize Dev\n");
X
- neigh_table_lock(&dn_neigh_table);


X for(i=0;i <= NEIGH_HASHMASK; i++) {

+ read_lock_bh(&dn_neigh_table.lock);
X n = dn_neigh_table.hash_buckets[i];
X for(; n != NULL; n = n->next) {
X struct dn_neigh *dn = (struct dn_neigh *)n;
X
+ read_lock(&n->lock);
X len += sprintf(buffer+len, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
X dn_addr2asc(dn_ntohs(dn_eth2dn(dn->addr)), buf),
X (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
@@ -576,6 +577,7 @@
X atomic_read(&dn->n.refcnt),
X dn->blksize,
X (dn->n.dev) ? dn->n.dev->name : "?");
+ read_unlock(&n->lock);
X
X pos = begin + len;
X
@@ -584,11 +586,15 @@
X begin = pos;
X }
X
- if (pos > offset + length)
- break;
+ if (pos > offset + length) {
+ read_unlock_bh(&dn_neigh_table.lock);
+ goto done;
+ }
X }
+ read_unlock_bh(&dn_neigh_table.lock);
X }
- neigh_table_unlock(&dn_neigh_table);
+
+done:


X
X *start = buffer + (offset - begin);

X len -= offset - begin;
diff -u --recursive --new-file v2.3.5/linux/net/ethernet/eth.c linux/net/ethernet/eth.c
--- v2.3.5/linux/net/ethernet/eth.c Wed Jun 2 14:44:39 1999
+++ linux/net/ethernet/eth.c Wed Jun 9 14:45:36 1999
@@ -248,6 +248,7 @@


X eth->h_proto = type;
X memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
X memcpy(eth->h_dest, neigh->ha, dev->addr_len);

+ hh->hh_len = ETH_HLEN;


X return 0;
X }
X

diff -u --recursive --new-file v2.3.5/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.3.5/linux/net/ipv4/af_inet.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/af_inet.c Wed Jun 9 14:45:36 1999
@@ -5,7 +5,7 @@
X *
X * PF_INET protocol family socket handler.
X *
- * Version: $Id: af_inet.c,v 1.90 1999/05/29 04:30:38 davem Exp $
+ * Version: $Id: af_inet.c,v 1.91 1999/06/09 08:28:55 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -371,7 +371,7 @@
X if (protocol && protocol != IPPROTO_UDP)
X goto free_and_noproto;
X protocol = IPPROTO_UDP;
- sk->no_check = UDP_NO_CHECK;
+ sk->no_check = UDP_CSUM_DEFAULT;
X sk->ip_pmtudisc = IP_PMTUDISC_DONT;
X prot=&udp_prot;
X sock->ops = &inet_dgram_ops;
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.3.5/linux/net/ipv4/arp.c Sun Mar 21 07:22:00 1999
+++ linux/net/ipv4/arp.c Wed Jun 9 14:45:36 1999
@@ -1,6 +1,6 @@
X /* linux/net/inet/arp.c
X *
- * Version: $Id: arp.c,v 1.77 1999/03/21 05:22:30 davem Exp $
+ * Version: $Id: arp.c,v 1.78 1999/06/09 10:10:36 davem Exp $
X *
X * Copyright (C) 1994 by Florian La Roche
X *
@@ -119,6 +119,11 @@
X #include <asm/system.h>
X #include <asm/uaccess.h>
X
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+static char *ax2asc2(ax25_address *a, char *buf);
+#endif
+
+
X /*
X * Interface to generic neighbour cache.
X */
@@ -304,7 +309,7 @@
X u8 *dst_ha = NULL;


X struct device *dev = neigh->dev;

X u32 target = *(u32*)neigh->primary_key;
- int probes = neigh->probes;
+ int probes = atomic_read(&neigh->probes);
X
X if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
X saddr = skb->nh.iph->saddr;
@@ -315,6 +320,7 @@
X if (!(neigh->nud_state&NUD_VALID))
X printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n");
X dst_ha = neigh->ha;
+ read_lock_bh(&neigh->lock);
X } else if ((probes -= neigh->parms->app_probes) < 0) {
X #ifdef CONFIG_ARPD
X neigh_app_ns(neigh);


@@ -324,6 +330,8 @@
X

X arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
X dst_ha, dev->dev_addr, NULL);
+ if (dst_ha)
+ read_unlock_bh(&neigh->lock);
X }
X
X /* OBSOLETE FUNCTIONS */
@@ -372,29 +380,25 @@
X if (arp_set_predefined(inet_addr_type(paddr), haddr, paddr, dev))
X return 0;
X
- start_bh_atomic();
X n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
X
X if (n) {
X n->used = jiffies;
X if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) {
- memcpy(haddr, n->ha, dev->addr_len);
+ read_lock_bh(&n->lock);
+ memcpy(haddr, n->ha, dev->addr_len);
+ read_unlock_bh(&n->lock);
X neigh_release(n);
- end_bh_atomic();
X return 0;
X }
+ neigh_release(n);
X } else
X kfree_skb(skb);
- neigh_release(n);


- end_bh_atomic();
X return 1;
X }
X

X /* END OF OBSOLETE FUNCTIONS */
X
-/*
- * Note: requires bh_atomic locking.
- */
X int arp_bind_neighbour(struct dst_entry *dst)
X {
X struct device *dev = dst->dev;
@@ -672,7 +676,8 @@
X (addr_type == RTN_UNICAST && rt->u.dst.dev != dev &&
X (IN_DEV_PROXY_ARP(in_dev) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
X n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
- neigh_release(n);
+ if (n)
+ neigh_release(n);
X
X if (skb->stamp.tv_sec == 0 ||
X skb->pkt_type == PACKET_HOST ||
@@ -785,7 +790,6 @@
X return -EINVAL;
X
X err = -ENOBUFS;
- start_bh_atomic();
X neigh = __neigh_lookup(&arp_tbl, &ip, dev, 1);
X if (neigh) {
X unsigned state = NUD_STALE;
@@ -795,7 +799,6 @@
X r->arp_ha.sa_data : NULL, state, 1, 0);
X neigh_release(neigh);
X }
- end_bh_atomic();


X return err;
X }
X

@@ -819,17 +822,17 @@
X struct neighbour *neigh;
X int err = -ENXIO;
X
- start_bh_atomic();
- neigh = __neigh_lookup(&arp_tbl, &ip, dev, 0);
+ neigh = neigh_lookup(&arp_tbl, &ip, dev);
X if (neigh) {
+ read_lock_bh(&neigh->lock);
X memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
+ r->arp_flags = arp_state_to_flags(neigh);
+ read_unlock_bh(&neigh->lock);
X r->arp_ha.sa_family = dev->type;
X strncpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
- r->arp_flags = arp_state_to_flags(neigh);
X neigh_release(neigh);
X err = 0;
X }
- end_bh_atomic();


X return err;
X }
X

@@ -867,14 +870,12 @@
X return -EINVAL;
X }
X err = -ENXIO;
- start_bh_atomic();
- neigh = __neigh_lookup(&arp_tbl, &ip, dev, 0);
+ neigh = neigh_lookup(&arp_tbl, &ip, dev);
X if (neigh) {
X if (neigh->nud_state&~NUD_NOARP)
X err = neigh_update(neigh, NULL, NUD_FAILED, 1, 0);
X neigh_release(neigh);
X }
- end_bh_atomic();


X return err;
X }
X

@@ -961,16 +962,16 @@
X char hbuffer[HBUFFERLEN];
X int i,j,k;
X const char hexbuf[] = "0123456789ABCDEF";
+ char abuf[16];
X
X size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n");
X

X pos+=size;
X len+=size;
X

- neigh_table_lock(&arp_tbl);
-
- for(i=0; i<=NEIGH_HASHMASK; i++) {
+ for(i=0; i<=NEIGH_HASHMASK; i++) {
X struct neighbour *n;
+ read_lock_bh(&arp_tbl.lock);
X for (n=arp_tbl.hash_buckets[i]; n; n=n->next) {
X struct device *dev = n->dev;
X int hatype = dev->type;
@@ -979,17 +980,14 @@
X if (!(n->nud_state&~NUD_NOARP))
X continue;
X
- /* I'd get great pleasure deleting
- this ugly code. Let's output it in hexadecimal format.
- "arp" utility will eventually repaired --ANK
- */
-#if 1 /* UGLY CODE */
+ read_lock(&n->lock);
+
X /*
X * Convert hardware address to XX:XX:XX:XX ... form.
X */
X #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
X if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
- strcpy(hbuffer,ax2asc((ax25_address *)n->ha));
+ ax2asc2((ax25_address *)n->ha, hbuffer);
X else {
X #endif
X for (k=0,j=0;k<HBUFFERLEN-3 && j<dev->addr_len;j++) {
@@ -998,37 +996,33 @@
X hbuffer[k++]=':';
X }
X hbuffer[--k]=0;
-
+
X #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
X }
X #endif
-#else
- if ((neigh->nud_state&NUD_VALID) && dev->addr_len) {
- int j;
- for (j=0; j < dev->addr_len; j++)
- sprintf(hbuffer+2*j, "%02x", neigh->ha[j]);
- } else
- sprintf(hbuffer, "0");
-#endif
X
X size = sprintf(buffer+len,
X "%-17s0x%-10x0x%-10x%s",
- in_ntoa(*(u32*)n->primary_key),
+ in_ntoa2(*(u32*)n->primary_key, abuf),
X hatype,
X arp_state_to_flags(n),
X hbuffer);
X size += sprintf(buffer+len+size,
X " %-17s %s\n",
X "*", dev->name);
+ read_unlock(&n->lock);
X
X len += size;
X pos += size;
X
X if (pos <= offset)
X len=0;
- if (pos >= offset+length)
- goto done;
+ if (pos >= offset+length) {
+ read_unlock_bh(&arp_tbl.lock);
+ goto done;
+ }
X }
+ read_unlock_bh(&arp_tbl.lock);
X }
X
X for (i=0; i<=PNEIGH_HASHMASK; i++) {
@@ -1039,7 +1033,7 @@
X
X size = sprintf(buffer+len,
X "%-17s0x%-10x0x%-10x%s",
- in_ntoa(*(u32*)n->key),
+ in_ntoa2(*(u32*)n->key, abuf),
X hatype,
X ATF_PUBL|ATF_PERM,
X "00:00:00:00:00:00");
@@ -1058,7 +1052,6 @@
X }
X
X done:
- neigh_table_unlock(&arp_tbl);
X
X *start = buffer+len-(pos-offset); /* Start of wanted data */
X len = pos-offset; /* Start slop */
@@ -1117,14 +1110,13 @@
X }
X
X
-#ifdef CONFIG_AX25_MODULE
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
X
X /*
X * ax25 -> ASCII conversion
X */
-char *ax2asc(ax25_address *a)
+char *ax2asc2(ax25_address *a, char *buf)
X {
- static char buf[11];
X char c, *s;
X int n;
X
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.3.5/linux/net/ipv4/devinet.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv4/devinet.c Wed Jun 9 14:45:36 1999
@@ -1,7 +1,7 @@
X /*
X * NET3 IP device support routines.
X *
- * Version: $Id: devinet.c,v 1.30 1999/06/01 07:49:59 davem Exp $
+ * Version: $Id: devinet.c,v 1.32 1999/06/09 11:15:33 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

@@ -636,10 +636,10 @@
X return done;
X }
X
-u32 inet_select_addr(struct device *dev, u32 dst, int scope)
+u32 inet_select_addr(const struct device *dev, u32 dst, int scope)
X {
X u32 addr = 0;


- struct in_device *in_dev = dev->ip_ptr;

+ const struct in_device *in_dev = dev->ip_ptr;
X
X if (in_dev == NULL)
X return 0;
@@ -659,19 +659,19 @@
X in this case. It is importnat that lo is the first interface
X in dev_base list.
X */
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev=dev_base; dev; dev=dev->next) {
X if ((in_dev=dev->ip_ptr) == NULL)
X continue;
X
X for_primary_ifa(in_dev) {
X if (ifa->ifa_scope <= scope) {
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X return ifa->ifa_local;
X }
X } endfor_ifa(in_dev);


X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X return 0;
X }
@@ -792,7 +792,7 @@
X
X s_idx = cb->args[0];
X s_ip_idx = ip_idx = cb->args[1];
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
X if (idx < s_idx)
X continue;
@@ -810,7 +810,7 @@
X }


X }
X done:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);

X cb->args[0] = idx;
X cb->args[1] = ip_idx;
X
@@ -885,13 +885,13 @@
X ipv4_devconf.accept_redirects = !on;
X ipv4_devconf_dflt.forwarding = on;


X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev; dev = dev->next) {

X struct in_device *in_dev = dev->ip_ptr;
X if (in_dev)
X in_dev->cnf.forwarding = on;


X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X rt_cache_flush(0);
X
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.3.5/linux/net/ipv4/fib_frontend.c Sun Mar 21 07:22:00 1999
+++ linux/net/ipv4/fib_frontend.c Wed Jun 9 14:45:36 1999
@@ -5,7 +5,7 @@
X *
X * IPv4 Forwarding Information Base: FIB frontend.
X *
- * Version: $Id: fib_frontend.c,v 1.15 1999/03/21 05:22:31 davem Exp $
+ * Version: $Id: fib_frontend.c,v 1.16 1999/06/09 10:10:42 davem Exp $
X *
X * Authors: Alexey Kuznetsov, <kuz...@ms2.inr.ac.ru>
X *
@@ -123,13 +123,11 @@
X first = 0;
X }
X
- /* rtnl_shlock(); -- it is pointless at the moment --ANK */
X if (main_table && count > 0) {
X int n = main_table->tb_get_info(main_table, ptr, first, count);
X count -= n;
X ptr += n*128;
X }
- /* rtnl_shunlock(); */
X len = ptr - *start;
X if (len >= length)
X return length;
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c
--- v2.3.5/linux/net/ipv4/fib_hash.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/fib_hash.c Wed Jun 9 14:45:36 1999
@@ -5,7 +5,7 @@
X *
X * IPv4 FIB: lookup engine and maintenance routines.
X *
- * Version: $Id: fib_hash.c,v 1.9 1999/05/27 00:38:05 davem Exp $
+ * Version: $Id: fib_hash.c,v 1.10 1999/06/09 10:10:45 davem Exp $
X *
X * Authors: Alexey Kuznetsov, <kuz...@ms2.inr.ac.ru>
X *
@@ -246,10 +246,10 @@
X fz->fz_mask = inet_make_mask(z);
X
X /* Find the first not empty zone with more specific mask */
- write_lock_bh(&fib_hash_lock);
X for (i=z+1; i<=32; i++)
X if (table->fn_zones[i])
X break;
+ write_lock_bh(&fib_hash_lock);
X if (i>32) {
X /* No more specific masks, we are the first. */
X fz->fz_next = table->fn_zone_list;
@@ -270,7 +270,7 @@
X struct fn_zone *fz;
X struct fn_hash *t = (struct fn_hash*)tb->tb_data;
X
- read_lock_bh(&fib_hash_lock);
+ read_lock(&fib_hash_lock);
X for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
X struct fib_node *f;
X fn_key_t k = fz_key(key->dst, fz);


@@ -307,7 +307,7 @@
X }

X err = 1;
X out:
- read_unlock_bh(&fib_hash_lock);
+ read_unlock(&fib_hash_lock);


X return err;
X }
X

@@ -353,7 +353,7 @@
X last_resort = NULL;
X order = -1;
X
- read_lock_bh(&fib_hash_lock);
+ read_lock(&fib_hash_lock);
X for (f = fz->fz_hash[0]; f; f = f->fn_next) {
X struct fib_info *next_fi = FIB_INFO(f);
X
@@ -395,7 +395,7 @@
X res->fi = last_resort;
X fn_hash_last_dflt = last_idx;
X out:
- read_unlock_bh(&fib_hash_lock);
+ read_unlock(&fib_hash_lock);
X }
X
X #define FIB_SCAN(f, fp) \
@@ -469,7 +469,6 @@
X
X fp = fz_chain_p(key, fz);
X
- write_lock_bh(&fib_hash_lock);
X
X /*
X * Scan list to find the first route with the same destination
@@ -574,12 +573,15 @@
X */
X
X new_f->fn_next = f;
+ write_lock_bh(&fib_hash_lock);
X *fp = new_f;
+ write_unlock_bh(&fib_hash_lock);
X fz->fz_nent++;
X
X if (del_fp) {
X f = *del_fp;
X /* Unlink replaced node */
+ write_lock_bh(&fib_hash_lock);
X *del_fp = f->fn_next;
X write_unlock_bh(&fib_hash_lock);
X
@@ -590,14 +592,12 @@
X fn_free_node(f);
X fz->fz_nent--;
X } else {
- write_unlock_bh(&fib_hash_lock);
X rt_cache_flush(-1);
X }
X rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->tb_id, n, req);
X return 0;
X
X out:
- write_unlock_bh(&fib_hash_lock);
X fib_release_info(fi);
X return err;
X }
@@ -635,13 +635,11 @@
X
X fp = fz_chain_p(key, fz);
X
- write_lock_bh(&fib_hash_lock);
X
X FIB_SCAN(f, fp) {
X if (fn_key_eq(f->fn_key, key))
X break;
X if (fn_key_leq(key, f->fn_key)) {
- write_unlock_bh(&fib_hash_lock);
X return -ESRCH;
X }
X }
@@ -658,7 +656,6 @@
X struct fib_info * fi = FIB_INFO(f);
X
X if (f->fn_state&FN_S_ZOMBIE) {
- write_unlock_bh(&fib_hash_lock);
X return -ESRCH;
X }
X matched++;
@@ -676,6 +673,7 @@
X rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
X
X if (matched != 1) {
+ write_lock_bh(&fib_hash_lock);
X *del_fp = f->fn_next;
X write_unlock_bh(&fib_hash_lock);
X
@@ -684,7 +682,6 @@
X fn_free_node(f);
X fz->fz_nent--;
X } else {
- write_unlock_bh(&fib_hash_lock);
X f->fn_state |= FN_S_ZOMBIE;
X if (f->fn_state&FN_S_ACCESSED) {
X f->fn_state &= ~FN_S_ACCESSED;
@@ -696,7 +693,6 @@
X
X return 0;
X }
- write_unlock_bh(&fib_hash_lock);
X return -ESRCH;
X }
X
@@ -710,7 +706,9 @@
X struct fib_info *fi = FIB_INFO(f);
X
X if (fi && ((f->fn_state&FN_S_ZOMBIE) || (fi->fib_flags&RTNH_F_DEAD))) {
+ write_lock_bh(&fib_hash_lock);
X *fp = f->fn_next;
+ write_unlock_bh(&fib_hash_lock);
X
X fn_free_node(f);
X found++;
@@ -728,7 +726,6 @@
X int found = 0;
X
X fib_hash_zombies = 0;
- write_lock_bh(&fib_hash_lock);
X for (fz = table->fn_zone_list; fz; fz = fz->fz_next) {
X int i;
X int tmp = 0;
@@ -737,7 +734,6 @@
X fz->fz_nent -= tmp;
X found += tmp;
X }
- write_unlock_bh(&fib_hash_lock);
X return found;
X }
X
@@ -751,7 +747,7 @@
X int pos = 0;
X int n = 0;
X
- read_lock_bh(&fib_hash_lock);
+ read_lock(&fib_hash_lock);
X for (fz=table->fn_zone_list; fz; fz = fz->fz_next) {
X int i;
X struct fib_node *f;


@@ -782,7 +778,7 @@
X }

X }
X out:
- read_unlock_bh(&fib_hash_lock);
+ read_unlock(&fib_hash_lock);
X return n;
X }
X #endif
@@ -845,18 +841,18 @@
X struct fn_hash *table = (struct fn_hash*)tb->tb_data;
X
X s_m = cb->args[1];
- read_lock_bh(&fib_hash_lock);
+ read_lock(&fib_hash_lock);
X for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
X if (m < s_m) continue;
X if (m > s_m)
X memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0]));
X if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
X cb->args[1] = m;
- read_unlock_bh(&fib_hash_lock);
+ read_unlock(&fib_hash_lock);


X return -1;
X }
X }

- read_unlock_bh(&fib_hash_lock);
+ read_unlock(&fib_hash_lock);
X cb->args[1] = m;
X return skb->len;
X }
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
--- v2.3.5/linux/net/ipv4/fib_rules.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/fib_rules.c Wed Jun 9 14:45:36 1999
@@ -5,7 +5,7 @@
X *
X * IPv4 Forwarding Information Base: policy rules.
X *
- * Version: $Id: fib_rules.c,v 1.10 1999/05/27 00:38:03 davem Exp $
+ * Version: $Id: fib_rules.c,v 1.11 1999/06/09 10:10:47 davem Exp $
X *
X * Authors: Alexey Kuznetsov, <kuz...@ms2.inr.ac.ru>
X *
@@ -88,7 +88,6 @@
X struct fib_rule *r, **rp;
X int err = -ESRCH;
X
- write_lock_bh(&fib_rules_lock);
X for (rp=&fib_rules; (r=*rp) != NULL; rp=&r->r_next) {
X if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) &&
X rtm->rtm_src_len == r->r_src_len &&
@@ -106,14 +105,15 @@
X if (r == &local_rule)
X break;
X
+ write_lock_bh(&fib_rules_lock);
X *rp = r->r_next;
+ write_unlock_bh(&fib_rules_lock);
X if (r != &default_rule && r != &main_rule)
X kfree(r);
X err = 0;
X break;
X }
X }
- write_unlock_bh(&fib_rules_lock);


X return err;
X }
X

@@ -192,7 +192,6 @@
X memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4);
X #endif
X
- write_lock_bh(&fib_rules_lock);
X rp = &fib_rules;
X if (!new_r->r_preference) {
X r = fib_rules;
@@ -210,6 +209,7 @@
X }
X
X new_r->r_next = r;
+ write_lock_bh(&fib_rules_lock);
X *rp = new_r;
X write_unlock_bh(&fib_rules_lock);
X return 0;
@@ -255,24 +255,26 @@
X {
X struct fib_rule *r;
X
- write_lock_bh(&fib_rules_lock);
X for (r=fib_rules; r; r=r->r_next) {
- if (r->r_ifindex == dev->ifindex)
+ if (r->r_ifindex == dev->ifindex) {
+ write_lock_bh(&fib_rules_lock);
X r->r_ifindex = -1;
+ write_unlock_bh(&fib_rules_lock);
+ }
X }
- write_unlock_bh(&fib_rules_lock);
X }
X
X static void fib_rules_attach(struct device *dev)
X {
X struct fib_rule *r;
X
- write_lock_bh(&fib_rules_lock);
X for (r=fib_rules; r; r=r->r_next) {
- if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
+ if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) {
+ write_lock_bh(&fib_rules_lock);
X r->r_ifindex = dev->ifindex;
+ write_unlock_bh(&fib_rules_lock);
+ }
X }
- write_unlock_bh(&fib_rules_lock);
X }
X
X int fib_lookup(const struct rt_key *key, struct fib_result *res)
@@ -285,7 +287,7 @@
X u32 saddr = key->src;
X
X FRprintk("Lookup: %08x <- %08x ", key->dst, key->src);
- read_lock_bh(&fib_rules_lock);
+ read_lock(&fib_rules_lock);
X for (r = fib_rules; r; r=r->r_next) {
X if (((saddr^r->r_src) & r->r_srcmask) ||
X ((daddr^r->r_dst) & r->r_dstmask) ||
@@ -305,14 +307,14 @@
X policy = r;
X break;
X case RTN_UNREACHABLE:
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);
X return -ENETUNREACH;
X default:
X case RTN_BLACKHOLE:
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);
X return -EINVAL;
X case RTN_PROHIBIT:
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);
X return -EACCES;
X }
X
@@ -322,16 +324,16 @@
X if (err == 0) {
X FRprintk("ok\n");
X res->r = policy;
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);
X return 0;
X }
X if (err < 0 && err != -EAGAIN) {
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);


X return err;
X }
X }

X FRprintk("FAILURE\n");
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);
X return -ENETUNREACH;
X }
X
@@ -418,14 +420,14 @@
X int s_idx = cb->args[0];
X struct fib_rule *r;
X
- read_lock_bh(&fib_rules_lock);
+ read_lock(&fib_rules_lock);
X for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
X if (idx < s_idx)
X continue;
X if (inet_fill_rule(skb, r, cb) < 0)
X break;
X }
- read_unlock_bh(&fib_rules_lock);
+ read_unlock(&fib_rules_lock);
X cb->args[0] = idx;
X
X return skb->len;
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.3.5/linux/net/ipv4/icmp.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv4/icmp.c Wed Jun 9 14:45:37 1999
@@ -3,7 +3,7 @@
X *
X * Alan Cox, <al...@redhat.com>
X *
- * Version: $Id: icmp.c,v 1.54 1999/05/30 01:16:22 davem Exp $
+ * Version: $Id: icmp.c,v 1.57 1999/06/09 10:10:50 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

@@ -699,8 +699,8 @@
X case ICMP_FRAG_NEEDED:
X if (ipv4_config.no_pmtu_disc) {
X if (net_ratelimit())
- printk(KERN_INFO "ICMP: %s: fragmentation needed and DF set.\n",
- in_ntoa(iph->daddr));
+ printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n",
+ NIPQUAD(iph->daddr));
X } else {
X unsigned short new_mtu;
X new_mtu = ip_rt_frag_needed(iph, ntohs(icmph->un.frag.mtu));
@@ -711,7 +711,7 @@
X break;
X case ICMP_SR_FAILED:
X if (net_ratelimit())
- printk(KERN_INFO "ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
+ printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr));
X break;
X default:
X break;
@@ -741,8 +741,8 @@
X if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
X {
X if (net_ratelimit())
- printk(KERN_WARNING "%s sent an invalid ICMP error to a broadcast.\n",
- in_ntoa(skb->nh.iph->saddr));
+ printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n",
+ NIPQUAD(skb->nh.iph->saddr));
X return;
X }
X }
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v2.3.5/linux/net/ipv4/igmp.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/igmp.c Wed Jun 9 14:45:37 1999
@@ -8,7 +8,7 @@
X * the older version didn't come out right using gcc 2.5.8, the newer one
X * seems to fall out with gcc 2.6.2.
X *
- * Version: $Id: igmp.c,v 1.31 1999/05/27 00:37:59 davem Exp $
+ * Version: $Id: igmp.c,v 1.32 1999/06/09 10:10:53 davem Exp $
X *
X * Authors:
X * Alan Cox <Alan...@linux.org>
@@ -97,6 +97,15 @@
X #include <linux/mroute.h>
X #endif
X
+/* Big mc list lock for all the devices */
+static rwlock_t ip_mc_lock = RW_LOCK_UNLOCKED;
+/* Big mc list semaphore for all the sockets.
+ We do not refer to this list in IP data paths or from BH,
+ so that semaphore is OK.
+ */
+DECLARE_MUTEX(ip_sk_mc_sem);
+
+
X #define IP_MAX_MEMBERSHIPS 20
X
X #ifdef CONFIG_IP_MULTICAST
@@ -216,6 +225,8 @@
X struct in_device *in_dev = im->interface;
X int err;
X
+ read_lock(&ip_mc_lock);
+
X im->tm_running=0;
X
X if (IGMP_V1_SEEN(in_dev))
@@ -234,6 +245,7 @@
X igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
X }
X im->reporter = 1;
+ read_unlock(&ip_mc_lock);
X }
X
X static void igmp_heard_report(struct in_device *in_dev, u32 group)
@@ -245,14 +257,16 @@
X if (LOCAL_MCAST(group))
X return;
X
+ read_lock(&ip_mc_lock);
X for (im=in_dev->mc_list; im!=NULL; im=im->next) {
X if (im->multiaddr == group) {
X igmp_stop_timer(im);
X im->reporter = 0;
X im->unsolicit_count = 0;
- return;
+ break;
X }
X }
+ read_unlock(&ip_mc_lock);
X }
X
X static void igmp_heard_query(struct in_device *in_dev, unsigned char max_resp_time,
@@ -281,6 +295,7 @@
X * - Use the igmp->igmp_code field as the maximum
X * delay possible
X */
+ read_lock(&ip_mc_lock);
X for (im=in_dev->mc_list; im!=NULL; im=im->next) {
X if (group && group != im->multiaddr)
X continue;
@@ -291,6 +306,7 @@
X igmp_stop_timer(im);
X igmp_start_timer(im, max_delay);
X }
+ read_unlock(&ip_mc_lock);
X }
X
X int igmp_rcv(struct sk_buff *skb, unsigned short len)
@@ -380,9 +396,7 @@
X if (LOCAL_MCAST(im->multiaddr))


X return;
X
- start_bh_atomic();

X igmp_stop_timer(im);
- end_bh_atomic();
X
X if (im->reporter && !IGMP_V1_SEEN(im->interface))
X igmp_send_report(im->interface->dev, im->multiaddr, IGMP_HOST_LEAVE_MESSAGE);
@@ -400,9 +414,7 @@
X if (LOCAL_MCAST(im->multiaddr))


X return;
X
- start_bh_atomic();

X igmp_start_timer(im, IGMP_Initial_Report_Delay);
- end_bh_atomic();
X #endif
X }
X
@@ -422,16 +434,17 @@
X
X im = (struct ip_mc_list *)kmalloc(sizeof(*im), GFP_KERNEL);
X
+ write_lock_bh(&ip_mc_lock);
X for (i=in_dev->mc_list; i; i=i->next) {
X if (i->multiaddr == addr) {
X i->users++;
X if (im)
X kfree(im);


- return;
+ goto out;
X }
X }

X if (!im)


- return;
+ goto out;

X im->users=1;
X im->interface=in_dev;
X im->multiaddr=addr;
@@ -447,9 +460,13 @@
X im->next=in_dev->mc_list;
X in_dev->mc_list=im;
X igmp_group_added(im);
+ write_unlock_bh(&ip_mc_lock);
X if (in_dev->dev->flags & IFF_UP)
X ip_rt_multicast_event(in_dev);
X return;
+out:
+ write_unlock_bh(&ip_mc_lock);
+ return;
X }
X
X /*


@@ -458,22 +475,27 @@
X

X int ip_mc_dec_group(struct in_device *in_dev, u32 addr)
X {
+ int err = -ESRCH;
X struct ip_mc_list *i, **ip;
X
+ write_lock_bh(&ip_mc_lock);
X for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
X if (i->multiaddr==addr) {
X if (--i->users == 0) {
X *ip = i->next;
- synchronize_bh();
-
X igmp_group_dropped(i);
+
+ write_unlock_bh(&ip_mc_lock);
X if (in_dev->dev->flags & IFF_UP)
X ip_rt_multicast_event(in_dev);
X kfree_s(i, sizeof(*i));
+ return 0;
X }
- return 0;
+ err = 0;
+ break;
X }
X }
+ write_unlock_bh(&ip_mc_lock);
X return -ESRCH;
X }
X
@@ -483,8 +505,10 @@
X {
X struct ip_mc_list *i;
X
+ read_lock_bh(&ip_mc_lock);
X for (i=in_dev->mc_list; i; i=i->next)
X igmp_group_dropped(i);
+ read_unlock_bh(&ip_mc_lock);
X
X ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
X }
@@ -497,8 +521,10 @@
X
X ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
X
+ read_lock_bh(&ip_mc_lock);
X for (i=in_dev->mc_list; i; i=i->next)
X igmp_group_added(i);
+ read_unlock_bh(&ip_mc_lock);
X }
X
X /*
@@ -509,11 +535,13 @@
X {
X struct ip_mc_list *i;
X
+ write_lock_bh(&ip_mc_lock);
X while ((i = in_dev->mc_list) != NULL) {
X in_dev->mc_list = i->next;
X igmp_group_dropped(i);
X kfree_s(i, sizeof(*i));
X }
+ write_unlock_bh(&ip_mc_lock);
X }
X
X static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
@@ -570,6 +598,7 @@
X iml = (struct ip_mc_socklist *)sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
X
X err = -EADDRINUSE;
+ down(&ip_sk_mc_sem);
X for (i=sk->ip_mc_list; i; i=i->next) {
X if (memcmp(&i->multi, imr, sizeof(*imr)) == 0) {
X /* New style additions are reference counted */
@@ -577,13 +606,13 @@
X i->count++;
X err = 0;
X }
- goto done;
+ goto done_unlock;
X }
X count++;
X }
X err = -ENOBUFS;
X if (iml == NULL || count >= sysctl_igmp_max_memberships)
- goto done;
+ goto done_unlock;
X memcpy(&iml->multi, imr, sizeof(*imr));
X iml->next = sk->ip_mc_list;
X iml->count = 1;
@@ -591,6 +620,9 @@
X ip_mc_inc_group(in_dev, addr);
X iml = NULL;
X err = 0;
+
+done_unlock:
+ up(&ip_sk_mc_sem);
X done:
X rtnl_shunlock();
X if (iml)
@@ -606,6 +638,7 @@
X {
X struct ip_mc_socklist *iml, **imlp;
X
+ down(&ip_sk_mc_sem);
X for (imlp=&sk->ip_mc_list; (iml=*imlp)!=NULL; imlp=&iml->next) {
X if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr &&
X iml->multi.imr_address.s_addr==imr->imr_address.s_addr &&
@@ -615,7 +648,7 @@
X return 0;
X
X *imlp = iml->next;
- synchronize_bh();
+ up(&ip_sk_mc_sem);
X
X in_dev = inetdev_by_index(iml->multi.imr_ifindex);
X if (in_dev)
@@ -624,6 +657,7 @@


X return 0;
X }
X }

+ up(&ip_sk_mc_sem);
X return -EADDRNOTAVAIL;
X }
X
@@ -635,13 +669,37 @@
X {
X struct ip_mc_socklist *iml;
X
+ down(&ip_sk_mc_sem);
X while ((iml=sk->ip_mc_list) != NULL) {
X struct in_device *in_dev;
X sk->ip_mc_list = iml->next;
+ up(&ip_sk_mc_sem);
+
X if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL)
X ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
X sock_kfree_s(sk, iml, sizeof(*iml));
+
+ down(&ip_sk_mc_sem);
X }
+ up(&ip_sk_mc_sem);
+}
+
+int ip_check_mc(struct device *dev, u32 mc_addr)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+ struct ip_mc_list *im;
+
+ if (in_dev) {
+ read_lock(&ip_mc_lock);
+ for (im=in_dev->mc_list; im; im=im->next) {
+ if (im->multiaddr == mc_addr) {
+ read_unlock(&ip_mc_lock);
+ return 1;
+ }
+ }
+ read_unlock(&ip_mc_lock);
+ }


+ return 0;
X }
X
X

@@ -653,10 +711,10 @@
X struct ip_mc_list *im;


X int len=0;
X struct device *dev;

-
+
X len=sprintf(buffer,"Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n");
-
- read_lock_bh(&dev_base_lock);
+
+ read_lock(&dev_base_lock);
X for(dev = dev_base; dev; dev = dev->next) {
X struct in_device *in_dev = dev->ip_ptr;
X char *querier = "NONE";
@@ -669,6 +727,7 @@
X len+=sprintf(buffer+len,"%d\t%-10s: %5d %7s\n",
X dev->ifindex, dev->name, dev->mc_count, querier);
X
+ read_lock(&ip_mc_lock);
X for (im = in_dev->mc_list; im; im = im->next) {
X len+=sprintf(buffer+len,
X "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
@@ -681,12 +740,15 @@


X len=0;
X begin=pos;
X }
- if(pos>offset+length)
+ if(pos>offset+length) {

+ read_unlock(&ip_mc_lock);


X goto done;
+ }
X }

+ read_unlock(&ip_mc_lock);


X }
X done:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X *start=buffer+(offset-begin);
X len-=(offset-begin);
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- v2.3.5/linux/net/ipv4/ip_input.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/ip_input.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * The Internet Protocol (IP) module.
X *
- * Version: $Id: ip_input.c,v 1.39 1999/05/30 01:16:25 davem Exp $
+ * Version: $Id: ip_input.c,v 1.40 1999/06/09 10:10:55 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -392,21 +392,17 @@
X if (skb->dst == NULL) {
X if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
X goto drop;
-#ifdef CONFIG_CPU_IS_SLOW
- if (net_cpu_congestion > 10 && !(iph->tos&IPTOS_RELIABILITY) &&
- IPTOS_PREC(iph->tos) < IPTOS_PREC_INTERNETCONTROL) {
- goto drop;
- }
-#endif
X }
X
X #ifdef CONFIG_NET_CLS_ROUTE
X if (skb->dst->tclassid) {
X u32 idx = skb->dst->tclassid;
+ write_lock(&ip_rt_acct_lock);
X ip_rt_acct[idx&0xFF].o_packets++;
X ip_rt_acct[idx&0xFF].o_bytes+=skb->len;
X ip_rt_acct[(idx>>16)&0xFF].i_packets++;
X ip_rt_acct[(idx>>16)&0xFF].i_bytes+=skb->len;
+ write_unlock(&ip_rt_acct_lock);
X }
X #endif
X
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/ip_masq_vdolive.c linux/net/ipv4/ip_masq_vdolive.c
--- v2.3.5/linux/net/ipv4/ip_masq_vdolive.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv4/ip_masq_vdolive.c Wed Jun 9 14:45:37 1999
@@ -2,7 +2,7 @@
X * IP_MASQ_VDOLIVE - VDO Live masquerading module
X *
X *
- * Version: @(#)$Id: ip_masq_vdolive.c,v 1.4 1998/10/06 04:49:07 davem Exp $
+ * Version: @(#)$Id: ip_masq_vdolive.c,v 1.6 1999/06/09 08:29:03 davem Exp $
X *
X * Author: Nigel Metheringham <Nigel.Met...@ThePLAnet.net>
X * PLAnet Online Ltd
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/ip_options.c linux/net/ipv4/ip_options.c
--- v2.3.5/linux/net/ipv4/ip_options.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv4/ip_options.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * The options processing module for ip.c
X *
- * Version: $Id: ip_options.c,v 1.16 1999/03/21 05:22:40 davem Exp $
+ * Version: $Id: ip_options.c,v 1.18 1999/06/09 08:29:06 davem Exp $
X *
X * Authors: A.N.Kuznetsov
X *
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.3.5/linux/net/ipv4/ipconfig.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/ipconfig.c Wed Jun 9 14:45:37 1999


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

- * $Id: ipconfig.c,v 1.21 1999/05/27 00:38:01 davem Exp $
+ * $Id: ipconfig.c,v 1.22 1999/06/09 10:10:57 davem Exp $
X *
X * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
X * information to configure own IP address and routes.
@@ -112,7 +112,7 @@
X unsigned short oflags;
X
X last = &ic_first_dev;


- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev; dev = dev->next) {

X if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
X (!(dev->flags & IFF_LOOPBACK) &&
@@ -144,7 +144,7 @@
X DBG(("IP-Config: Opened %s (able=%d)\n", dev->name, able));


X }
X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X *last = NULL;
X
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.3.5/linux/net/ipv4/ipmr.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv4/ipmr.c Wed Jun 9 14:45:37 1999
@@ -9,7 +9,7 @@


X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X *

- * Version: $Id: ipmr.c,v 1.40 1999/03/25 10:04:25 davem Exp $
+ * Version: $Id: ipmr.c,v 1.43 1999/06/09 10:10:59 davem Exp $


X *
X * Fixes:

X * Michael Chastain : Incorrect size of copying.
@@ -23,6 +23,8 @@
X * Brad Parker : Better behaviour on mrouted upcall
X * overflow.
X * Carlos Picoto : PIMv1 Support
+ * Pavlin Ivanov Radoslavov: PIMv2 Registers must checksum only PIM header
+ * Relax this requrement to work with older peers.


X *
X */
X

@@ -431,7 +433,7 @@
X skb_trim(skb, nlh->nlmsg_len);
X ((struct nlmsgerr*)NLMSG_DATA(nlh))->error = -EMSGSIZE;
X }
- err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+ err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT);
X } else
X #endif
X ip_mr_forward(skb, cache, 0);
@@ -1343,7 +1345,8 @@
X pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
X (pim->flags&PIM_NULL_REGISTER) ||
X reg_dev == NULL ||
- ip_compute_csum((void *)pim, len)) {
+ (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
+ ip_compute_csum((void *)pim, len))) {
X kfree_skb(skb);
X return -EINVAL;
X }
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.5/linux/net/ipv4/route.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/route.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * ROUTE - implementation of the IP router.
X *
- * Version: $Id: route.c,v 1.68 1999/05/27 00:37:54 davem Exp $
+ * Version: $Id: route.c,v 1.69 1999/06/09 10:11:02 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -1996,6 +1996,7 @@
X
X #ifdef CONFIG_NET_CLS_ROUTE
X struct ip_rt_acct ip_rt_acct[256];
+rwlock_t ip_rt_acct_lock = RW_LOCK_UNLOCKED;
X
X #ifdef CONFIG_PROC_FS
X static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
@@ -2008,9 +2009,9 @@


X *eof = 1;
X }

X if (length > 0) {
- start_bh_atomic();
+ read_lock_bh(&ip_rt_acct_lock);
X memcpy(buffer, ((u8*)&ip_rt_acct)+offset, length);
- end_bh_atomic();
+ read_unlock_bh(&ip_rt_acct_lock);
X return length;
X }
X return 0;
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.3.5/linux/net/ipv4/tcp_input.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv4/tcp_input.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * Implementation of the Transmission Control Protocol(TCP).
X *
- * Version: $Id: tcp_input.c,v 1.167 1999/05/29 22:37:54 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.169 1999/06/09 08:29:13 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.5/linux/net/ipv4/tcp_ipv4.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/tcp_ipv4.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * Implementation of the Transmission Control Protocol(TCP).
X *
- * Version: $Id: tcp_ipv4.c,v 1.178 1999/05/30 01:16:27 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.180 1999/06/09 08:29:19 davem Exp $
X *
X * IPv4 specific functions
X *
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.3.5/linux/net/ipv4/udp.c Mon May 31 22:28:07 1999
+++ linux/net/ipv4/udp.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * The User Datagram Protocol (UDP).
X *
- * Version: $Id: udp.c,v 1.67 1999/05/27 00:37:50 davem Exp $
+ * Version: $Id: udp.c,v 1.69 1999/06/09 11:15:31 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -173,7 +173,7 @@


X return 0;
X }
X

-/* Shared by v4/v6 tcp. */
+/* Shared by v4/v6 udp. */
X unsigned short udp_good_socknum(void)
X {
X int result;
@@ -763,7 +763,10 @@
X /* 4.1.3.4. It's configurable by the application via setsockopt() */
X /* (MAY) and it defaults to on (MUST). */
X
- err = ip_build_xmit(sk,sk->no_check ? udp_getfrag_nosum : udp_getfrag,
+ err = ip_build_xmit(sk,
+ (sk->no_check == UDP_CSUM_NOXMIT ?
+ udp_getfrag_nosum :
+ udp_getfrag),
X &ufh, ulen, &ipc, rt, msg->msg_flags);
X
X out:
@@ -1093,6 +1096,33 @@
X }
X #endif
X
+static int udp_checksum_verify(struct sk_buff *skb, struct udphdr *uh,
+ unsigned short ulen, u32 saddr, u32 daddr,
+ int full_csum_deferred)
+{
+ if (!full_csum_deferred) {
+ if (uh->check) {
+ if (skb->ip_summed == CHECKSUM_HW &&
+ udp_check(uh, ulen, saddr, daddr, skb->csum))
+ return -1;
+ if (skb->ip_summed == CHECKSUM_NONE &&
+ udp_check(uh, ulen, saddr, daddr,
+ csum_partial((char *)uh, ulen, 0)))
+ return -1;
+ }
+ } else {
+ if (uh->check == 0)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else if (skb->ip_summed == CHECKSUM_HW) {
+ if (udp_check(uh, ulen, saddr, daddr, skb->csum))
+ return -1;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+ skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+ }


+ return 0;
+}
+

X /*
X * All we need to do is get the socket, and then do a checksum.
X */
@@ -1134,25 +1164,18 @@
X }
X skb_trim(skb, ulen);
X
-#ifndef CONFIG_UDP_DELAY_CSUM
- if (uh->check &&
- (((skb->ip_summed==CHECKSUM_HW)&&udp_check(uh,ulen,saddr,daddr,skb->csum)) ||
- ((skb->ip_summed==CHECKSUM_NONE) &&
- (udp_check(uh,ulen,saddr,daddr, csum_partial((char*)uh, ulen, 0))))))
- goto csum_error;
+ if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) {
+ int defer;
+
+#ifdef CONFIG_UDP_DELAY_CSUM
+ defer = 1;
X #else
- if (uh->check==0)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else if (skb->ip_summed==CHECKSUM_HW) {
- if (udp_check(uh,ulen,saddr,daddr,skb->csum))
- goto csum_error;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
- skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+ defer = 0;
X #endif
-
- if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
+ if (udp_checksum_verify(skb, uh, ulen, saddr, daddr, defer))
+ goto csum_error;
X return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
+ }
X
X #ifdef CONFIG_IP_TRANSPARENT_PROXY
X if (IPCB(skb)->redirport)
@@ -1179,6 +1202,15 @@
X kfree_skb(skb);
X return(0);
X }
+ if (udp_checksum_verify(skb, uh, ulen, saddr, daddr,
+#ifdef CONFIG_UDP_DELAY_CSUM
+ 1
+#else
+ (sk->no_check & UDP_CSUM_NORCV) != 0
+#endif
+ ))
+ goto csum_error;
+
X udp_deliver(sk, skb);
X return 0;
X
diff -u --recursive --new-file v2.3.5/linux/net/ipv4/utils.c linux/net/ipv4/utils.c
--- v2.3.5/linux/net/ipv4/utils.c Mon Jan 12 15:28:28 1998
+++ linux/net/ipv4/utils.c Wed Jun 9 14:45:37 1999
@@ -6,7 +6,7 @@
X * Various kernel-resident INET utility functions; mainly
X * for format conversion and debugging output.
X *
- * Version: $Id: utils.c,v 1.6 1997/12/13 21:53:03 kuznet Exp $
+ * Version: $Id: utils.c,v 1.7 1999/06/09 10:11:05 davem Exp $
X *
X * Author: Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
X *
@@ -57,6 +57,11 @@
X return(buff);
X }
X
+char *in_ntoa2(__u32 in, char *buff)
+{
+ sprintf(buff, "%d.%d.%d.%d", NIPQUAD(in));
+ return buff;
+}
X
X /*
X * Convert an ASCII string to binary IP.
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.5/linux/net/ipv6/addrconf.c Mon May 31 22:28:07 1999
+++ linux/net/ipv6/addrconf.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *
- * $Id: addrconf.c,v 1.49 1999/05/27 00:38:20 davem Exp $
+ * $Id: addrconf.c,v 1.50 1999/06/09 10:11:09 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

@@ -100,9 +100,7 @@
X 1. The result of inet6_add_addr() is used only inside lock
X or from bh_atomic context.
X
- 2. inet6_get_lladdr() is used only from bh protected context.
-
- 3. The result of ipv6_chk_addr() is not used outside of bh protected context.
+ 2. The result of ipv6_chk_addr() is not used outside of bh protected context.
X */
X
X static __inline__ void addrconf_lock(void)
@@ -463,7 +461,7 @@


X return err;
X }
X

-struct inet6_ifaddr * ipv6_get_lladdr(struct device *dev)
+int ipv6_get_lladdr(struct device *dev, struct in6_addr *addr)
X {
X struct inet6_ifaddr *ifp = NULL;
X struct inet6_dev *idev;
@@ -471,12 +469,15 @@
X if ((idev = ipv6_get_idev(dev)) != NULL) {
X addrconf_lock();
X for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
- if (ifp->scope == IFA_LINK)
- break;
+ if (ifp->scope == IFA_LINK) {
+ ipv6_addr_copy(addr, &ifp->addr);
+ addrconf_unlock();


+ return 0;
+ }
X }

X addrconf_unlock();
X }
- return ifp;
+ return -EADDRNOTAVAIL;
X }
X
X /*
@@ -982,7 +983,7 @@
X return;
X }
X

- read_lock_bh(&dev_base_lock);
+ read_lock(&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;
@@ -1001,7 +1002,6 @@
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) {
@@ -1013,11 +1013,10 @@
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);
+ read_unlock(&dev_base_lock);
X }
X

X static void init_loopback(struct device *dev)
@@ -1846,12 +1845,11 @@
X struct device *dev;
X
X /* This takes sense only during module load. */


- read_lock_bh(&dev_base_lock);
+ read_lock(&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);
@@ -1862,9 +1860,8 @@
X default:
X /* Ignore all other */
X }
- read_lock_bh(&dev_base_lock);


X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);

X #endif
X
X #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.3.5/linux/net/ipv6/af_inet6.c Thu Apr 22 19:45:20 1999
+++ linux/net/ipv6/af_inet6.c Wed Jun 9 14:45:37 1999
@@ -7,7 +7,7 @@
X *
X * Adapted from linux/net/ipv4/af_inet.c
X *
- * $Id: af_inet6.c,v 1.43 1999/04/22 10:07:39 davem Exp $
+ * $Id: af_inet6.c,v 1.44 1999/06/09 08:29:29 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

@@ -103,7 +103,7 @@
X if (protocol && protocol != IPPROTO_UDP)
X goto free_and_noproto;
X protocol = IPPROTO_UDP;
- sk->no_check = UDP_NO_CHECK;
+ sk->no_check = UDP_CSUM_DEFAULT;
X prot=&udpv6_prot;
X sock->ops = &inet6_dgram_ops;
X } else if(sock->type == SOCK_RAW) {
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/ip6_fw.c linux/net/ipv6/ip6_fw.c
--- v2.3.5/linux/net/ipv6/ip6_fw.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv6/ip6_fw.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *
- * $Id: ip6_fw.c,v 1.10 1998/08/26 12:04:57 davem Exp $
+ * $Id: ip6_fw.c,v 1.12 1999/06/09 08:29:32 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

@@ -383,7 +383,7 @@
X }
X
X #ifdef MODULE


-void module_cleanup(void)
+void cleanup_module(void)
X {

X #ifdef CONFIG_NETLINK
X netlink_detach(NETLINK_IP6_FW);
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c
--- v2.3.5/linux/net/ipv6/ip6_output.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv6/ip6_output.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *
- * $Id: ip6_output.c,v 1.17 1999/04/22 10:07:42 davem Exp $
+ * $Id: ip6_output.c,v 1.20 1999/06/09 10:11:12 davem Exp $
X *
X * Based on linux/net/ipv4/ip_output.c
X *
@@ -75,19 +75,10 @@
X }
X
X if (hh) {
-#ifdef __alpha__
- /* Alpha has disguisting memcpy. Help it. */
- u64 *aligned_hdr = (u64*)(skb->data - 16);
- u64 *aligned_hdr0 = hh->hh_data;
- read_lock_irq(&hh->hh_lock);
- aligned_hdr[0] = aligned_hdr0[0];
- aligned_hdr[1] = aligned_hdr0[1];
-#else


- read_lock_irq(&hh->hh_lock);
+ read_lock_bh(&hh->hh_lock);
X memcpy(skb->data - 16, hh->hh_data, 16);

-#endif


- read_unlock_irq(&hh->hh_lock);
- skb_push(skb, dev->hard_header_len);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
X return hh->hh_output(skb);
X } else if (dst->neighbour)
X return dst->neighbour->output(skb);

diff -u --recursive --new-file v2.3.5/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.5/linux/net/ipv6/mcast.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv6/mcast.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *
- * $Id: mcast.c,v 1.20 1999/05/27 00:38:23 davem Exp $
+ * $Id: mcast.c,v 1.23 1999/06/09 10:11:14 davem Exp $
X *
X * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
X *
@@ -53,6 +53,11 @@
X #define MDBG(x)
X #endif
X
+/* Big mc list lock for all the devices */
+static rwlock_t ipv6_mc_lock = RW_LOCK_UNLOCKED;
+/* Big mc list lock for all the sockets */
+static rwlock_t ipv6_sk_mc_lock = RW_LOCK_UNLOCKED;
+
X static struct socket *igmp6_socket;
X
X static void igmp6_join_group(struct ifmcaddr6 *ma);
@@ -115,8 +120,10 @@


X return err;
X }
X

+ write_lock_bh(&ipv6_sk_mc_lock);
X mc_lst->next = np->ipv6_mc_list;
X np->ipv6_mc_list = mc_lst;
+ write_unlock_bh(&ipv6_sk_mc_lock);


X
X return 0;
X }

@@ -129,13 +136,14 @@
X struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
X struct ipv6_mc_socklist *mc_lst, **lnk;
X
+ write_lock_bh(&ipv6_sk_mc_lock);
X for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
X if (mc_lst->ifindex == ifindex &&
X ipv6_addr_cmp(&mc_lst->addr, addr) == 0) {


X struct device *dev;
X

X *lnk = mc_lst->next;
- synchronize_bh();
+ write_unlock_bh(&ipv6_sk_mc_lock);
X
X if ((dev = dev_get_by_index(ifindex)) != NULL)
X ipv6_dev_mc_dec(dev, &mc_lst->addr);
@@ -143,6 +151,7 @@


X return 0;
X }
X }

+ write_unlock_bh(&ipv6_sk_mc_lock);
X
X return -ENOENT;
X }
@@ -152,15 +161,38 @@
X struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
X struct ipv6_mc_socklist *mc_lst;
X
+ write_lock_bh(&ipv6_sk_mc_lock);
X while ((mc_lst = np->ipv6_mc_list) != NULL) {
- struct device *dev = dev_get_by_index(mc_lst->ifindex);


+ struct device *dev;
+

+ np->ipv6_mc_list = mc_lst->next;
+ write_unlock_bh(&ipv6_sk_mc_lock);
X
+ dev = dev_get_by_index(mc_lst->ifindex);
X if (dev)
X ipv6_dev_mc_dec(dev, &mc_lst->addr);
X
- np->ipv6_mc_list = mc_lst->next;
X sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part24

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


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

if test "$Scheck" != 24; then


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

+ write_lock_bh(&ipv6_sk_mc_lock);
X }
+ write_unlock_bh(&ipv6_sk_mc_lock);
+}
+
+int inet6_mc_check(struct sock *sk, struct in6_addr *addr)
+{
+ struct ipv6_mc_socklist *mc;
+
+ read_lock(&ipv6_sk_mc_lock);
+ for (mc = sk->net_pinfo.af_inet6.ipv6_mc_list; mc; mc=mc->next) {
+ if (ipv6_addr_cmp(&mc->addr, addr) == 0) {
+ read_unlock(&ipv6_sk_mc_lock);


+ return 1;
+ }
+ }

+ read_unlock(&ipv6_sk_mc_lock);


+
+ return 0;
X }
X

X static int igmp6_group_added(struct ifmcaddr6 *mc)
@@ -210,9 +242,11 @@
X
X hash = ipv6_addr_hash(addr);
X
+ write_lock_bh(&ipv6_mc_lock);
X for (mc = inet6_mcast_lst[hash]; mc; mc = mc->next) {
X if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0 && mc->dev == dev) {
X atomic_inc(&mc->mca_users);
+ write_unlock_bh(&ipv6_mc_lock);


X return 0;
X }
X }

@@ -223,8 +257,10 @@
X
X mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);
X
- if (mc == NULL)
+ if (mc == NULL) {
+ write_unlock_bh(&ipv6_mc_lock);


X return -ENOMEM;
+ }
X

X memset(mc, 0, sizeof(struct ifmcaddr6));
X mc->mca_timer.function = igmp6_timer_handler;
@@ -242,6 +278,8 @@
X
X igmp6_group_added(mc);
X
+ write_unlock_bh(&ipv6_mc_lock);
+


X return 0;
X }
X

@@ -257,7 +295,6 @@
X for (lnk = &idev->mc_list; (iter = *lnk) != NULL; lnk = &iter->if_next) {
X if (iter == ma) {
X *lnk = iter->if_next;
- synchronize_bh();
X return;
X }
X }
@@ -274,20 +311,22 @@
X
X hash = ipv6_addr_hash(addr);
X
+ write_lock_bh(&ipv6_mc_lock);
X for (lnk = &inet6_mcast_lst[hash]; (ma=*lnk) != NULL; lnk = &ma->next) {
X if (ipv6_addr_cmp(&ma->mca_addr, addr) == 0 && ma->dev == dev) {
X if (atomic_dec_and_test(&ma->mca_users)) {
X igmp6_group_dropped(ma);
X
X *lnk = ma->next;
- synchronize_bh();
X
X ipv6_mca_remove(dev, ma);
X kfree(ma);
X }
+ write_unlock_bh(&ipv6_mc_lock);


X return 0;
X }
X }

+ write_unlock_bh(&ipv6_mc_lock);


X
X return -ENOENT;
X }

@@ -302,10 +341,14 @@
X
X hash = ipv6_addr_hash(addr);
X
+ read_lock_bh(&ipv6_mc_lock);
X for (mc = inet6_mcast_lst[hash]; mc; mc=mc->next) {
- if (mc->dev == dev && ipv6_addr_cmp(&mc->mca_addr, addr) == 0)
+ if (mc->dev == dev && ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
+ read_unlock_bh(&ipv6_mc_lock);
X return 1;
+ }
X }
+ read_unlock_bh(&ipv6_mc_lock);


X
X return 0;
X }

@@ -364,11 +407,14 @@
X if (idev == NULL)
X return 0;
X
+ read_lock(&ipv6_mc_lock);
X for (ma = idev->mc_list; ma; ma=ma->if_next)
X igmp6_group_queried(ma, resptime);
+ read_unlock(&ipv6_mc_lock);
X } else {
X int hash = ipv6_addr_hash(addrp);
X
+ read_lock(&ipv6_mc_lock);
X for (ma = inet6_mcast_lst[hash]; ma; ma=ma->next) {
X if (ma->dev == skb->dev &&
X ipv6_addr_cmp(addrp, &ma->mca_addr) == 0) {
@@ -376,6 +422,7 @@
X break;
X }
X }
+ read_unlock(&ipv6_mc_lock);
X }
X
X return 0;
@@ -410,6 +457,7 @@
X
X hash = ipv6_addr_hash(addrp);
X
+ read_lock(&ipv6_mc_lock);
X for (ma = inet6_mcast_lst[hash]; ma; ma=ma->next) {
X if ((ma->dev == dev) && ipv6_addr_cmp(&ma->mca_addr, addrp) == 0) {
X if (ma->mca_flags & MAF_TIMER_RUNNING) {
@@ -421,6 +469,7 @@
X break;
X }
X }
+ read_unlock(&ipv6_mc_lock);


X
X return 0;
X }

@@ -430,9 +479,9 @@
X struct sock *sk = igmp6_socket->sk;
X struct sk_buff *skb;
X struct icmp6hdr *hdr;
- struct inet6_ifaddr *ifp;
X struct in6_addr *snd_addr;
X struct in6_addr *addrp;
+ struct in6_addr addr_buf;
X struct in6_addr all_routers;
X int err, len, payload_len, full_len;
X u8 ra[8] = { IPPROTO_ICMPV6, 0,
@@ -461,9 +510,7 @@
X dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len);
X }
X
- ifp = ipv6_get_lladdr(dev);
-
- if (ifp == NULL) {
+ if (ipv6_get_lladdr(dev, &addr_buf)) {
X #if MCAST_DEBUG >= 1
X printk(KERN_DEBUG "igmp6: %s no linklocal address\n",
X dev->name);
@@ -471,7 +518,7 @@
X return;
X }
X
- ip6_nd_hdr(sk, skb, dev, &ifp->addr, snd_addr, NEXTHDR_HOP, payload_len);
+ ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
X
X memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
X
@@ -482,7 +529,7 @@
X addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
X ipv6_addr_copy(addrp, addr);
X
- hdr->icmp6_cksum = csum_ipv6_magic(&ifp->addr, snd_addr, len,
+ hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,
X IPPROTO_ICMPV6,
X csum_partial((__u8 *) hdr, len, 0));
X
@@ -504,7 +551,6 @@
X if ((addr_type & (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_LOOPBACK)))


X return;
X
- start_bh_atomic();

X igmp6_send(&ma->mca_addr, ma->dev, ICMPV6_MGM_REPORT);
X
X delay = net_random() % IGMP6_UNSOLICITED_IVAL;
@@ -515,7 +561,6 @@
X
X add_timer(&ma->mca_timer);
X ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
- end_bh_atomic();
X }
X
X static void igmp6_leave_group(struct ifmcaddr6 *ma)
@@ -527,22 +572,22 @@
X if ((addr_type & IPV6_ADDR_LINKLOCAL))


X return;
X
- start_bh_atomic();

X if (ma->mca_flags & MAF_LAST_REPORTER)
X igmp6_send(&ma->mca_addr, ma->dev, ICMPV6_MGM_REDUCTION);
X
X if (ma->mca_flags & MAF_TIMER_RUNNING)
X del_timer(&ma->mca_timer);
- end_bh_atomic();
X }
X
X void igmp6_timer_handler(unsigned long data)
X {
X struct ifmcaddr6 *ma = (struct ifmcaddr6 *) data;
X
+ read_lock(&ipv6_mc_lock);
X ma->mca_flags |= MAF_LAST_REPORTER;
X igmp6_send(&ma->mca_addr, ma->dev, ICMPV6_MGM_REPORT);
X ma->mca_flags &= ~MAF_TIMER_RUNNING;
+ read_unlock(&ipv6_mc_lock);
X }
X
X /* Device going down */
@@ -554,8 +599,10 @@
X
X /* Withdraw multicast list */
X
+ read_lock_bh(&ipv6_mc_lock);
X for (i = idev->mc_list; i; i=i->if_next)
X igmp6_group_dropped(i);
+ read_unlock_bh(&ipv6_mc_lock);
X
X /* Delete all-nodes address. */
X
@@ -577,8 +624,10 @@
X
X /* Install multicast list, except for all-nodes (already installed) */
X
+ read_lock(&ipv6_mc_lock);
X for (i = idev->mc_list; i; i=i->if_next)
X igmp6_group_added(i);
+ read_unlock(&ipv6_mc_lock);
X }
X
X /*
@@ -590,6 +639,7 @@
X int hash;
X struct ifmcaddr6 *i, **lnk;
X
+ write_lock_bh(&ipv6_mc_lock);
X while ((i = idev->mc_list) != NULL) {
X idev->mc_list = i->if_next;
X
@@ -598,13 +648,13 @@
X for (lnk = &inet6_mcast_lst[hash]; *lnk; lnk = &(*lnk)->next) {
X if (*lnk == i) {
X *lnk = i->next;
- synchronize_bh();
X break;
X }
X }
X igmp6_group_dropped(i);
X kfree(i);
X }
+ write_unlock_bh(&ipv6_mc_lock);


X }
X
X #ifdef CONFIG_PROC_FS

@@ -616,13 +666,14 @@


X int len=0;
X struct device *dev;

X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X for (dev = dev_base; dev; dev = dev->next) {

X struct inet6_dev *idev;
X
X if ((idev = ipv6_get_idev(dev)) == NULL)
X continue;
X
+ read_lock_bh(&ipv6_mc_lock);
X for (im = idev->mc_list; im; im = im->if_next) {
X int i;
X
@@ -642,14 +693,17 @@


X len=0;
X begin=pos;
X }

- if (pos > offset+length)
+ if (pos > offset+length) {

+ read_unlock_bh(&ipv6_mc_lock);


X goto done;
+ }
X }

+ read_unlock_bh(&ipv6_mc_lock);
X }


X *eof = 1;
X

X done:
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X
X *start=buffer+(offset-begin);
X len-=(offset-begin);

diff -u --recursive --new-file v2.3.5/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.3.5/linux/net/ipv6/ndisc.c Thu Apr 22 19:45:20 1999
+++ linux/net/ipv6/ndisc.c Wed Jun 9 14:45:37 1999
@@ -268,14 +268,21 @@
X ndisc_mc_map(daddr, ha, dev, 1);
X h_dest = ha;
X } else if (neigh) {
- h_dest = neigh->ha;
+ read_lock_bh(&neigh->lock);
+ if (neigh->nud_state&NUD_VALID) {
+ memcpy(ha, neigh->ha, dev->addr_len);
+ h_dest = ha;
+ }
+ read_unlock_bh(&neigh->lock);
X } else {
X neigh = neigh_lookup(&nd_tbl, daddr, dev);


X if (neigh) {
+ read_lock_bh(&neigh->lock);

X if (neigh->nud_state&NUD_VALID) {
X memcpy(ha, neigh->ha, dev->addr_len);
X h_dest = ha;
X }
+ read_unlock_bh(&neigh->lock);
X neigh_release(neigh);
X }
X }
@@ -362,6 +369,7 @@
X struct sock *sk = ndisc_socket->sk;
X struct sk_buff *skb;
X struct nd_msg *msg;
+ struct in6_addr addr_buf;
X int len;
X int err;
X
@@ -377,13 +385,8 @@
X }
X
X if (saddr == NULL) {
- struct inet6_ifaddr *ifa;
-
- /* use link local address */
- ifa = ipv6_get_lladdr(dev);
-
- if (ifa)
- saddr = &ifa->addr;
+ if (!ipv6_get_lladdr(dev, &addr_buf))
+ saddr = &addr_buf;
X }
X
X if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
@@ -501,13 +504,15 @@
X kfree_skb(skb);
X }
X
+/* Called with locked neigh: either read or both */
+
X static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
X {
X struct in6_addr *saddr = NULL;
X struct in6_addr mcaddr;


X struct device *dev = neigh->dev;

X struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;


- int probes = neigh->probes;
+ int probes = atomic_read(&neigh->probes);
X

X if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 0))
X saddr = &skb->nh.ipv6h->saddr;
@@ -774,8 +779,8 @@
X struct sock *sk = ndisc_socket->sk;
X int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
X struct sk_buff *buff;
- struct inet6_ifaddr *ifp;
X struct icmp6hdr *icmph;
+ struct in6_addr saddr_buf;
X struct in6_addr *addrp;
X struct device *dev;
X struct rt6_info *rt;
@@ -817,12 +822,10 @@
X rd_len &= ~0x7;
X len += rd_len;
X
- ifp = ipv6_get_lladdr(dev);
-
- if (ifp == NULL) {
- ND_PRINTK1("redirect: no link_local addr for dev\n");
- return;
- }
+ if (ipv6_get_lladdr(dev, &saddr_buf)) {
+ ND_PRINTK1("redirect: no link_local addr for dev\n");
+ return;
+ }
X
X buff = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
X 0, 0, &err);
@@ -838,7 +841,7 @@
X return;
X }
X
- ip6_nd_hdr(sk, buff, dev, &ifp->addr, &skb->nh.ipv6h->saddr,
+ ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
X IPPROTO_ICMPV6, len);
X
X icmph = (struct icmp6hdr *) skb_put(buff, len);
@@ -875,7 +878,7 @@
X
X memcpy(opt, skb->nh.ipv6h, rd_len - 8);
X
- icmph->icmp6_cksum = csum_ipv6_magic(&ifp->addr, &skb->nh.ipv6h->saddr,
+ icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr,
X len, IPPROTO_ICMPV6,
X csum_partial((u8 *) icmph, len, 0));
X
@@ -1034,7 +1037,7 @@
X ifp->idev->dev->name);
X return 0;
X }
- neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 0);
+ neigh = neigh_lookup(&nd_tbl, &msg->target, skb->dev);
X
X if (neigh) {
X if (neigh->flags & NTF_ROUTER) {
@@ -1083,11 +1086,10 @@


X unsigned long now = jiffies;
X int i;
X

- neigh_table_lock(&nd_tbl);
-
X for (i = 0; i <= NEIGH_HASHMASK; i++) {


X struct neighbour *neigh;
X

+ read_lock_bh(&nd_tbl.lock);
X for (neigh = nd_tbl.hash_buckets[i]; neigh; neigh = neigh->next) {
X int j;
X
@@ -1097,6 +1099,7 @@
X size += 2;
X }
X
+ read_lock(&neigh->lock);
X size += sprintf(buffer+len+size,
X " %02x %02x %02x %02x %08lx %08lx %08x %04x %04x %04x %8s ", i,
X 128,
@@ -1118,19 +1121,22 @@
X } else {
X size += sprintf(buffer+len+size, "000000000000");
X }
+ read_unlock(&neigh->lock);
X size += sprintf(buffer+len+size, "\n");


X len += size;
X pos += size;
X
X if (pos <= offset)
X len=0;
- if (pos >= offset+length)

+ if (pos >= offset+length) {

+ read_unlock_bh(&nd_tbl.lock);


X goto done;
+ }
X }

+ read_unlock_bh(&nd_tbl.lock);
X }
X
X done:
- neigh_table_unlock(&nd_tbl);


X
X *start = buffer+len-(pos-offset); /* Start of wanted data */
X len = pos-offset; /* Start slop */

diff -u --recursive --new-file v2.3.5/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
--- v2.3.5/linux/net/ipv6/raw.c Mon May 31 22:28:07 1999
+++ linux/net/ipv6/raw.c Wed Jun 9 14:45:37 1999


@@ -7,7 +7,7 @@
X *

X * Adapted from linux/net/ipv4/raw.c
X *
- * $Id: raw.c,v 1.25 1999/05/27 00:38:16 davem Exp $
+ * $Id: raw.c,v 1.26 1999/06/09 10:11: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

@@ -99,17 +99,6 @@
X SOCKHASH_UNLOCK_WRITE();
X }
X
-static __inline__ int inet6_mc_check(struct sock *sk, struct in6_addr *addr)
-{
- struct ipv6_mc_socklist *mc;
-
- for (mc = sk->net_pinfo.af_inet6.ipv6_mc_list; mc; mc=mc->next) {
- if (ipv6_addr_cmp(&mc->addr, addr) == 0)


- return 1;
- }
-

- return 0;
-}
X

X /* Grumble... icmp and ip_input want to get at this... */
X struct sock *raw_v6_lookup(struct sock *sk, unsigned short num,
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/reassembly.c linux/net/ipv6/reassembly.c
--- v2.3.5/linux/net/ipv6/reassembly.c Wed Jun 2 14:44:39 1999
+++ linux/net/ipv6/reassembly.c Wed Jun 9 14:45:37 1999


@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *

- * $Id: reassembly.c,v 1.11 1998/08/26 12:05:16 davem Exp $
+ * $Id: reassembly.c,v 1.13 1999/06/09 08:29:40 davem Exp $
X *
X * Based on: net/ipv4/ip_fragment.c
X *
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.3.5/linux/net/ipv6/route.c Sun Mar 21 07:22:00 1999
+++ linux/net/ipv6/route.c Wed Jun 9 14:45:37 1999


@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *

- * $Id: route.c,v 1.35 1999/03/21 05:22:57 davem Exp $
+ * $Id: route.c,v 1.36 1999/06/09 10:11:21 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

@@ -1607,7 +1607,7 @@


X return 0;
X }
X

-static int fib6_dump_done(struct netlink_callback *cb)
+static void fib6_dump_end(struct netlink_callback *cb)
X {
X struct fib6_walker_t *w = (void*)cb->args[0];
X
@@ -1622,6 +1622,11 @@
X cb->done = (void*)cb->args[1];
X cb->args[1] = 0;
X }
+}
+
+static int fib6_dump_done(struct netlink_callback *cb)
+{
+ fib6_dump_end(cb);
X return cb->done(cb);
X }
X
@@ -1668,11 +1673,15 @@
X if (res <= 0 && skb->len == 0)
X RT6_TRACE("%p>dump end\n", w);
X #endif
+ res = res < 0 ? res : skb->len;
X /* res < 0 is an error. (really, impossible)
X res == 0 means that dump is complete, but skb still can contain data.
X res > 0 dump is not complete, but frame is full.
X */
- return res < 0 ? res : skb->len;
+ /* Destroy walker, if dump of this table is complete. */
+ if (res <= 0)
+ fib6_dump_end(cb);
+ return res;
X }
X
X int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.3.5/linux/net/ipv6/tcp_ipv6.c Mon May 31 22:28:07 1999
+++ linux/net/ipv6/tcp_ipv6.c Wed Jun 9 14:45:37 1999


@@ -5,7 +5,7 @@
X * Authors:
X * Pedro Roque <ro...@di.fc.ul.pt>
X *

- * $Id: tcp_ipv6.c,v 1.106 1999/05/27 01:12:44 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.108 1999/06/09 08:29:43 davem Exp $
X *
X * Based on:
X * linux/net/ipv4/tcp.c
diff -u --recursive --new-file v2.3.5/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.3.5/linux/net/ipv6/udp.c Mon May 31 22:28:07 1999
+++ linux/net/ipv6/udp.c Wed Jun 9 14:45:37 1999


@@ -7,7 +7,7 @@
X *

X * Based on linux/ipv4/udp.c
X *
- * $Id: udp.c,v 1.41 1999/05/27 00:38:18 davem Exp $
+ * $Id: udp.c,v 1.42 1999/06/09 10:11:24 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

@@ -499,18 +499,6 @@
X }
X ipv6_statistics.Ip6InDelivers++;
X udp_stats_in6.UdpInDatagrams++;


- return 0;
-}
-

-static __inline__ int inet6_mc_check(struct sock *sk, struct in6_addr *addr)
-{
- struct ipv6_mc_socklist *mc;
-
- for (mc = sk->net_pinfo.af_inet6.ipv6_mc_list; mc; mc=mc->next) {
- if (ipv6_addr_cmp(&mc->addr, addr) == 0)


- return 1;
- }
-

X return 0;
X }
X

diff -u --recursive --new-file v2.3.5/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.3.5/linux/net/irda/Config.in Thu Apr 15 05:42:42 1999
+++ linux/net/irda/Config.in Mon Jun 7 16:18:58 1999
@@ -2,34 +2,31 @@
X # IrDA protocol configuration
X #
X
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- if [ "$CONFIG_NET" != "n" ] ; then
+if [ "$CONFIG_NET" != "n" ] ; then
X
- mainmenu_option next_comment
- comment 'IrDA subsystem support'
- dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_EXPERIMENTAL $CONFIG_NET
+ mainmenu_option next_comment
+ comment 'IrDA subsystem support'
+ dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
X
- if [ "$CONFIG_IRDA" != "n" ] ; then
- comment 'IrDA protocols'
- source net/irda/irlan/Config.in
- source net/irda/ircomm/Config.in
- source net/irda/irlpt/Config.in
+ if [ "$CONFIG_IRDA" != "n" ] ; then
+ comment 'IrDA protocols'
+ source net/irda/irlan/Config.in
+ source net/irda/ircomm/Config.in
+ source net/irda/irlpt/Config.in
X
- bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
- if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
- comment ' IrDA options'
- bool ' Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
- bool ' Fast RRs' CONFIG_IRDA_FAST_RR
- bool ' Debug information' CONFIG_IRDA_DEBUG
- fi
+ bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
+ if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
+ comment ' IrDA options'
+ bool ' Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
+ bool ' Fast RRs' CONFIG_IRDA_FAST_RR
+ bool ' Debug information' CONFIG_IRDA_DEBUG
X fi
+ fi
X
- if [ "$CONFIG_IRDA" != "n" ] ; then
- source net/irda/compressors/Config.in
- source drivers/net/irda/Config.in
- fi
- endmenu
-
+ if [ "$CONFIG_IRDA" != "n" ] ; then
+ source net/irda/compressors/Config.in
+ source drivers/net/irda/Config.in
X fi
+ endmenu
X fi
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.5/linux/net/irda/af_irda.c Mon May 31 22:28:07 1999
+++ linux/net/irda/af_irda.c Mon Jun 7 16:18:58 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: Tue May 11 12:42:26 1999
+ * Modified at: Wed May 19 16:12:06 1999


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

X * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
X *
@@ -145,7 +145,7 @@
X else
X self->max_data_size = max_sdu_size;
X
- DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+ DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
X
X memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
X
@@ -189,7 +189,7 @@
X else
X self->max_data_size = max_sdu_size;
X
- DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+ DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
X
X memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
X
@@ -250,12 +250,12 @@
X
X switch (flow) {
X case FLOW_STOP:
- DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n");
+ DEBUG(1, __FUNCTION__ "(), IrTTP wants us to slow down\n");
X self->tx_flow = flow;
X break;
X case FLOW_START:
X self->tx_flow = flow;
- DEBUG(0, __FUNCTION__ "(), IrTTP wants us to start again\n");
+ DEBUG(1, __FUNCTION__ "(), IrTTP wants us to start again\n");
X wake_up_interruptible(sk->sleep);
X break;
X default:
@@ -703,7 +703,11 @@
X
X sock_init_data(sock, sk);
X
- sock->ops = &irda_stream_ops;
+ if (sock->type == SOCK_STREAM)
+ sock->ops = &irda_stream_ops;
+ else
+ sock->ops = &irda_dgram_ops;
+
X sk->protocol = protocol;
X
X /* Register as a client with IrLMP */
@@ -1123,7 +1127,7 @@
X {
X struct sock *sk = sock->sk;
X
- DEBUG(0, __FUNCTION__ "(), cmd=%#x\n", cmd);
+ DEBUG(4, __FUNCTION__ "(), cmd=%#x\n", cmd);
X
X switch (cmd) {
X case TIOCOUTQ: {
@@ -1170,7 +1174,7 @@
X return -EINVAL;
X
X default:
- DEBUG(0, __FUNCTION__ "(), doing device ioctl!\n");
+ DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n");
X return dev_ioctl(cmd, (void *) arg);
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/discovery.c linux/net/irda/discovery.c
--- v2.3.5/linux/net/irda/discovery.c Wed Jun 2 14:44:39 1999
+++ linux/net/irda/discovery.c Mon Jun 7 16:18:58 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 May 9 22:40:43 1999
+ * Modified at: Fri May 28 20:46:38 1999


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

X * Modified at: Fri May 28 3:11 CST 1999
X * Modified by: Horst von Brand <vonb...@sleipnir.valparaiso.cl>
@@ -227,10 +227,12 @@
X
X discovery = (discovery_t *) hashbin_get_first(cachelog);
X while ( discovery != NULL) {
- len += sprintf( buf+len, " name: %s,",
- discovery->info);
+ len += sprintf(buf+len, "name: %s,", discovery->info);
X
- len += sprintf( buf+len, " hint: ");
+ len += sprintf(buf+len, " hint: 0x%02x%02x",
+ discovery->hints.byte[0],
+ discovery->hints.byte[1]);
+#if 0
X if ( discovery->hints.byte[0] & HINT_PNP)
X len += sprintf( buf+len, "PnP Compatible ");
X if ( discovery->hints.byte[0] & HINT_PDA)
@@ -254,14 +256,14 @@
X len += sprintf( buf+len, "IrCOMM ");
X if ( discovery->hints.byte[1] & HINT_OBEX)
X len += sprintf( buf+len, "IrOBEX ");
-
+#endif
X len += sprintf(buf+len, ", saddr: 0x%08x",
X discovery->saddr);
X
X len += sprintf(buf+len, ", daddr: 0x%08x\n",
X discovery->daddr);
X
- len += sprintf( buf+len, "\n");
+ len += sprintf(buf+len, "\n");
X
X discovery = (discovery_t *) hashbin_get_next(cachelog);
X }
diff -u --recursive --new-file v2.3.5/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.3.5/linux/net/irda/ircomm/ircomm_common.c Mon May 31 22:28:07 1999
+++ linux/net/irda/ircomm/ircomm_common.c Mon Jun 7 16:18:58 1999
@@ -41,7 +41,7 @@
X
X #include <net/irda/ircomm_common.h>
X
-static char *revision_date = "Sun Apr 18 00:40:19 1999";
+static char *revision_date = "Tue May 18 03:11:39 1999";
X
X
X static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
@@ -205,15 +205,17 @@
X ircomm[i]->enq_char = 0x05;
X ircomm[i]->ack_char = 0x06;
X
- ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE; /* 64 */
- ircomm[i]->max_sdu_size = SAR_DISABLE;
- ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+ ircomm[i]->max_header_size = COMM_MAX_HEADER_SIZE;
+ ircomm[i]->tx_max_sdu_size = COMM_DEFAULT_SDU_SIZE;
+ ircomm[i]->rx_max_sdu_size = SAR_DISABLE;
+ ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE
+ + COMM_MAX_HEADER_SIZE);
X if (ircomm[i]->ctrl_skb == NULL){
X DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
X return -ENOMEM;
X }
X
- skb_reserve(ircomm[i]->ctrl_skb,COMM_HEADER_SIZE);
+ skb_reserve(ircomm[i]->ctrl_skb,COMM_MAX_HEADER_SIZE);
X
X }
X
@@ -302,14 +304,16 @@
X DEBUG(0,__FUNCTION__"(): got connected!\n");
X
X if (max_sdu_size == SAR_DISABLE)
- self->max_txbuff_size = qos->data_size.value - max_header_size;
+ self->tx_max_sdu_size =(qos->data_size.value - max_header_size
+ - COMM_HEADER_SIZE);
X else {
- ASSERT(max_sdu_size >= COMM_DEFAULT_DATA_SIZE, return;);
- self->max_txbuff_size = max_sdu_size; /* use fragmentation */
+ ASSERT(max_sdu_size >= COMM_DEFAULT_SDU_SIZE, return;);
+ /* use fragmentation */
+ self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE;
X }
X
X self->qos = qos;
- self->max_header_size = max_header_size;
+ self->max_header_size = max_header_size + COMM_HEADER_SIZE;
X self->null_modem_mode = 0; /* disable null modem emulation */
X
X ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb);
@@ -331,12 +335,13 @@
X DEBUG(0,__FUNCTION__"()\n");
X
X if (max_sdu_size == SAR_DISABLE)
- self->max_txbuff_size = qos->data_size.value - max_header_size;
+ self->tx_max_sdu_size =(qos->data_size.value - max_header_size
+ - COMM_HEADER_SIZE);
X else
- self->max_txbuff_size = max_sdu_size;
+ self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE;
X
X self->qos = qos;
- self->max_header_size = max_header_size;
+ self->max_header_size = max_header_size + COMM_HEADER_SIZE;
X
X ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
X
@@ -558,7 +563,7 @@
X
X irttp_connect_request(self->tsap, self->dlsap,
X self->saddr, self->daddr,
- NULL, self->max_sdu_size, userdata);
+ NULL, self->rx_max_sdu_size, userdata);
X break;
X
X default:
@@ -592,7 +597,8 @@
X
X if (self->notify.connect_indication)
X self->notify.connect_indication(self->notify.instance, self,
- qos, 0, 0, skb);
+ qos, self->tx_max_sdu_size,
+ self->max_header_size, skb);
X }
X
X #if 0
@@ -611,7 +617,8 @@
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, 0, skb);
+ self, NULL, self->tx_max_sdu_size,
+ self->max_header_size, skb);
X }
X
X static void issue_connect_response(struct ircomm_cb *self,
@@ -623,7 +630,7 @@
X DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
X /* irlmp_connect_rsp(); */
X } else
- irttp_connect_response(self->tsap, self->max_sdu_size, skb);
+ irttp_connect_response(self->tsap, self->rx_max_sdu_size, skb);
X }
X
X static void issue_disconnect_request(struct ircomm_cb *self,
@@ -1054,7 +1061,7 @@
X
X hints = irlmp_service_to_hint(S_COMM);
X
- DEBUG(0,__FUNCTION__"():start discovering..\n");
+ DEBUG(1,__FUNCTION__"():start discovering..\n");
X switch (ircomm_cs) {
X case 0:
X MOD_INC_USE_COUNT;
@@ -1155,12 +1162,12 @@
X ASSERT( self->magic == IRCOMM_MAGIC, return;);
X
X
- DEBUG(0, __FUNCTION__"():sending connect_request...\n");
+ DEBUG(1, __FUNCTION__"():sending connect_request...\n");
X
X self->servicetype= servicetype;
X /* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/
X
- self->max_sdu_size = SAR_DISABLE;
+ self->rx_max_sdu_size = SAR_DISABLE;
X ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL);
X }
X
@@ -1181,20 +1188,18 @@
X
X if (!userdata){
X /* FIXME: check for errors and initialize? DB */
- userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+ userdata = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
X if (userdata == NULL)
X return;
X
- skb_reserve(userdata,COMM_HEADER_SIZE);
+ skb_reserve(userdata,COMM_MAX_HEADER_SIZE);
X }
X
X /* enable null-modem emulation (i.e. server mode )*/
X self->null_modem_mode = 1;
X
- self->max_sdu_size = max_sdu_size;
- if (max_sdu_size != SAR_DISABLE)
- self->max_txbuff_size = max_sdu_size;
-
+ self->rx_max_sdu_size = max_sdu_size;
+
X ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
X }
X
@@ -1307,10 +1312,10 @@
X ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
X self->control_ch_pending = 0;
X
- skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+ skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
X ASSERT(skb != NULL, return ;);
X
- skb_reserve(skb,COMM_HEADER_SIZE);
+ skb_reserve(skb,COMM_MAX_HEADER_SIZE);
X self->ctrl_skb = skb;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c
--- v2.3.5/linux/net/irda/ircomm/irvtd_driver.c Mon May 31 22:28:07 1999
+++ linux/net/irda/ircomm/irvtd_driver.c Mon Jun 7 16:18:58 1999
@@ -51,7 +51,7 @@
X static int irvtd_refcount;
X struct irvtd_cb **irvtd = NULL;
X
-static char *revision_date = "Sun Apr 18 17:31:53 1999";
+static char *revision_date = "Wed May 26 00:49:11 1999";
X
X
X /*
@@ -83,8 +83,10 @@
X static void irvtd_send_xchar(struct tty_struct *tty, char ch);
X static void irvtd_wait_until_sent(struct tty_struct *tty, int timeout);
X
-static void irvtd_start_timer( struct irvtd_cb *driver);
-static void irvtd_timer_expired(unsigned long data);
+static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout);
+static void irvtd_tx_timer_expired(unsigned long data);
+static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout);
+static void irvtd_rx_timer_expired(unsigned long data);
X
X static int line_info(char *buf, struct irvtd_cb *driver);
X static int irvtd_read_proc(char *buf, char **start, off_t offset, int len,
@@ -118,7 +120,7 @@
X if(driver->rx_disable)
X return;
X
- skb = skb_dequeue(&driver->rxbuff);
+ skb = skb_dequeue(&driver->rxbuff);
X if(skb == NULL)
X return; /* there's nothing */
X
@@ -211,8 +213,13 @@
X
X if(skb_queue_len(&driver->rxbuff)< IRVTD_RX_QUEUE_LOW &&
X driver->ttp_stoprx){
- irttp_flow_request(driver->comm->tsap, FLOW_START);
+ DEBUG(1, __FUNCTION__"():FLOW_START\n");
+ /*
+ * next 2 lines must follow this order since irttp_flow_request()
+ * will run its rx queue
+ */
X driver->ttp_stoprx = 0;
+ irttp_flow_request(driver->comm->tsap, FLOW_START);
X }
X
X if(skb_queue_empty(&driver->rxbuff) && driver->disconnect_pend){
@@ -236,10 +243,14 @@
X skb_queue_tail( &driver->rxbuff, skb );
X
X if(skb_queue_len(&driver->rxbuff) > IRVTD_RX_QUEUE_HIGH){
+ DEBUG(1, __FUNCTION__"():FLOW_STOP\n");
X irttp_flow_request(driver->comm->tsap, FLOW_STOP);
X driver->ttp_stoprx = 1;
X }
X irvtd_write_to_tty(driver);
+
+ if(!skb_queue_empty(&driver->rxbuff))
+ irvtd_start_rx_timer(driver,0);


X return 0;
X }
X

@@ -255,22 +266,36 @@
X */
X
X
-static void irvtd_start_timer( struct irvtd_cb *driver)
+static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout)
+{
+ ASSERT( driver != NULL, return;);
+ ASSERT( driver->magic == IRVTD_MAGIC, return;);
+
+ del_timer( &driver->tx_timer);
+
+ driver->tx_timer.data = (unsigned long) driver;
+ driver->tx_timer.function = &irvtd_tx_timer_expired;
+ driver->tx_timer.expires = jiffies + timeout;
+
+ add_timer( &driver->tx_timer);
+}
+
+static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout)
X {
X ASSERT( driver != NULL, return;);
X ASSERT( driver->magic == IRVTD_MAGIC, return;);
X
- del_timer( &driver->timer);
+ del_timer( &driver->rx_timer);
X
- driver->timer.data = (unsigned long) driver;
- driver->timer.function = &irvtd_timer_expired;
- driver->timer.expires = jiffies + (HZ / 5); /* 200msec */
+ driver->rx_timer.data = (unsigned long) driver;
+ driver->rx_timer.function = &irvtd_rx_timer_expired;
+ driver->rx_timer.expires = jiffies + timeout;
X
- add_timer( &driver->timer);
+ add_timer( &driver->rx_timer);
X }
X
X
-static void irvtd_timer_expired(unsigned long data)
+static void irvtd_tx_timer_expired(unsigned long data)
X {
X struct irvtd_cb *driver = (struct irvtd_cb *)data;
X
@@ -279,11 +304,26 @@
X DEBUG(4, __FUNCTION__"()\n");
X
X irvtd_send_data_request(driver);
+}
X
- irvtd_write_to_tty(driver);
+static void irvtd_rx_timer_expired(unsigned long data)
+{
+ struct irvtd_cb *driver = (struct irvtd_cb *)data;
+
+ ASSERT(driver != NULL,return;);
+ ASSERT(driver->magic == IRVTD_MAGIC,return;);


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

- /* start our timer again and again */
- irvtd_start_timer(driver);
+ while(TTY_FLIPBUF_SIZE - driver->tty->flip.count
+ && !skb_queue_empty(&driver->rxbuff))
+ irvtd_write_to_tty(driver);
+
+ DEBUG(1, __FUNCTION__"(): room in flip_buffer = %d\n",
+ TTY_FLIPBUF_SIZE - driver->tty->flip.count);
+
+ if(!skb_queue_empty(&driver->rxbuff))
+ /* handle it later */
+ irvtd_start_rx_timer(driver, 1);
X }
X
X
@@ -310,21 +350,23 @@
X }
X #endif
X
- DEBUG(1, __FUNCTION__"():sending %d octets\n",(int)skb->len );
+ DEBUG(1, __FUNCTION__"():len = %d, room = %d\n",(int)skb->len,
+ skb_tailroom(skb));
X driver->icount.tx += skb->len;
X err = ircomm_data_request(driver->comm, driver->txbuff);
X if (err){
X ASSERT(err == 0,;);
- DEBUG(0,"%d chars are lost\n",(int)skb->len);
+ DEBUG(1,"%d chars are lost\n",(int)skb->len);
X skb_trim(skb, 0);
X }
X
X /* allocate a new frame */
- skb = driver->txbuff = dev_alloc_skb(driver->comm->max_txbuff_size);
+ skb = driver->txbuff
+ = dev_alloc_skb(driver->tx_max_sdu_size + driver->max_header_size);
X if (skb == NULL){
X printk(__FUNCTION__"():alloc_skb failed!\n");
X } else {
- skb_reserve(skb, COMM_HEADER_SIZE);
+ skb_reserve(skb, driver->max_header_size);
X }
X
X wake_up_interruptible(&driver->tty->write_wait);
@@ -355,6 +397,9 @@
X ASSERT(driver != NULL, return;);
X ASSERT(driver->magic == IRVTD_MAGIC, return;);
X
+
+ driver->tx_max_sdu_size = max_sdu_size;
+ driver->max_header_size = max_header_size;
X /*
X * set default value
X */
@@ -408,6 +453,8 @@
X ASSERT(comm != NULL, return;);
X ASSERT(comm->magic == IRCOMM_MAGIC, return;);
X
+ driver->tx_max_sdu_size = max_sdu_size;
+ driver->max_header_size = max_header_size;
X DEBUG(4, __FUNCTION__ "():sending connect_response...\n");
X
X ircomm_connect_response(comm, NULL, SAR_DISABLE );
@@ -481,11 +528,12 @@
X if(cmd == TX_READY){
X driver->ttp_stoptx = 0;
X driver->tty->hw_stopped = driver->cts_stoptx;
- irvtd_start_timer( driver);
X
X if(driver->cts_stoptx)
X return;
X
+ /* push tx queue so that client can send at least 1 octet */
+ irvtd_send_data_request(driver);
X /*
X * driver->tty->write_wait will keep asleep if
X * our txbuff is full.
@@ -500,7 +548,7 @@
X
X if(cmd == TX_BUSY){
X driver->ttp_stoptx = driver->tty->hw_stopped = 1;
- del_timer( &driver->timer);
+ del_timer( &driver->tx_timer);
X return;
X }
X
@@ -681,7 +729,7 @@
X
X driver->blocked_open--;
X
- DEBUG(0, __FUNCTION__"():after blocking\n");
+ DEBUG(1, __FUNCTION__"():after blocking\n");
X
X if (retval)
X return retval;
@@ -768,7 +816,7 @@
X struct notify_t irvtd_notify;
X
X /* FIXME: it should not be hard coded */
- __u8 oct_seq[6] = { 0,1,4,1,1,1 };
+ __u8 oct_seq[6] = { 0,1,6,1,1,1 };
X
X DEBUG(4,__FUNCTION__"()\n" );
X if(driver->flags & ASYNC_INITIALIZED)
@@ -779,12 +827,12 @@
X */
X
X skb_queue_head_init(&driver->rxbuff);
- driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+ driver->txbuff = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
X if (!driver->txbuff){
X DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n");
X return -ENOMEM;
X }
- skb_reserve(driver->txbuff, COMM_HEADER_SIZE);
+ skb_reserve(driver->txbuff, COMM_MAX_HEADER_SIZE);
X
X irda_notify_init(&irvtd_notify);
X irvtd_notify.data_indication = irvtd_receive_data;
@@ -813,22 +861,20 @@
X
X driver->flags |= ASYNC_INITIALIZED;
X
- /*
- * discover a peer device
- * TODO: other servicetype(i.e. 3wire,3wireraw) support
- */
- ircomm_connect_request(driver->comm, NINE_WIRE);
-
- /*
- * TODO:we have to initialize control-channel here!
- * i.e.set something into RTS,CTS and so on....
- */
-
X if (driver->tty)
X clear_bit(TTY_IO_ERROR, &driver->tty->flags);
X
X change_speed(driver);
- irvtd_start_timer( driver);
+
+ /*
+ * discover a peer device
+ */
+ if(driver->tty->termios->c_cflag & CRTSCTS)
+ ircomm_connect_request(driver->comm, NINE_WIRE);
+ else
+ ircomm_connect_request(driver->comm, THREE_WIRE);
+
+ /* irvtd_start_timer( driver); */
X
X driver->rx_disable = 0;
X driver->tx_disable = 1;
@@ -991,7 +1037,8 @@
X if (driver->tty)
X set_bit(TTY_IO_ERROR, &driver->tty->flags);
X
- del_timer( &driver->timer);
+ del_timer( &driver->tx_timer);
+ del_timer( &driver->rx_timer);
X
X irias_delete_object("IrDA:IrCOMM");
X
@@ -1146,13 +1193,21 @@
X DEBUG(4, __FUNCTION__"()\n");
X
X save_flags(flags);
- while(1){
+ while(count > 0){
X cli();
X skb = driver->txbuff;
X ASSERT(skb != NULL, break;);
X c = MIN(count, (skb_tailroom(skb)));
X if (c <= 0)
- break;
+ {
+ if(!driver->ttp_stoptx)
+ {
+ irvtd_send_data_request(driver);
+ continue;
+ }


+ else
+ break;
+ }

X
X /* write to the frame */
X
@@ -1166,9 +1221,9 @@
X wrote += c;
X count -= c;
X buf += c;
- irvtd_send_data_request(driver);
X }
X restore_flags(flags);
+ irvtd_send_data_request(driver);
X return (wrote);
X }
X
@@ -1201,19 +1256,27 @@
X DEBUG(4, __FUNCTION__"()\n");
X
X
+ again:
X save_flags(flags);cli();
X skb = driver->txbuff;
X ASSERT(skb != NULL,return;);
+ if(!skb_tailroom(skb))
+ {
+ restore_flags(flags);
+ irvtd_send_data_request(driver);
+ goto again;
+ }
X ASSERT(skb_tailroom(skb) > 0, return;);
- DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) MAX(%d):\n",
+ DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) room(%d):\n",
X (int)ch ,(int)skb->len,
- driver->comm->max_txbuff_size - COMM_HEADER_SIZE);
+ skb_tailroom(skb));
X
X /* append a character */
X frame = skb_put(skb,1);
X frame[0] = ch;
X
X restore_flags(flags);
+ irvtd_start_tx_timer(driver,20);
X return;
X }
X
@@ -1637,6 +1700,7 @@
X driver->comm->dte = driver->mcr;
X ircomm_control_request(driver->comm, DTELINE_STATE );
X
+ DEBUG(1, __FUNCTION__"():FLOW_STOP\n");
X irttp_flow_request(driver->comm->tsap, FLOW_STOP);
X }
X
@@ -1651,6 +1715,7 @@
X driver->comm->dte = driver->mcr;
X ircomm_control_request(driver->comm, DTELINE_STATE );
X
+ DEBUG(1, __FUNCTION__"():FLOW_START\n");
X irttp_flow_request(driver->comm->tsap, FLOW_START);
X }
X
@@ -1860,6 +1925,12 @@
X ret += sprintf(buf+ret, "|CD");
X if (driver->msr & MSR_RI)
X ret += sprintf(buf+ret, "|RI");
+
+ ret += sprintf(buf+ret, "\n");
+ ret += sprintf(buf+ret, "rx queue:%d",
+ skb_queue_len( &driver->rxbuff));
+ ret += sprintf(buf+ret, "ttp_stoprx:%s",
+ driver->ttp_stoprx?"TRUE":"FALSE");
X
X exit:
X ret += sprintf(buf+ret, "\n");
diff -u --recursive --new-file v2.3.5/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.5/linux/net/irda/irda_device.c Wed Jun 2 14:44:39 1999
+++ linux/net/irda/irda_device.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@


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

X * Created at: Wed Sep 2 20:22:08 1998


- * Modified at: Mon May 10 23:02:47 1999

+ * Modified at: Tue Jun 1 09:05:13 1999


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

X * Modified at: Fri May 28 3:11 CST 1999
X * Modified by: Horst von Brand <vonb...@sleipnir.valparaiso.cl>
@@ -105,6 +105,12 @@
X #ifdef CONFIG_NSC_FIR
X pc87108_init();
X #endif
+#ifdef CONFIG_TOSHIBA_FIR
+ toshoboe_init();
+#endif
+#ifdef CONFIG_SMC_IRCC_FIR
+ ircc_init();
+#endif
X #ifdef CONFIG_ESI_DONGLE
X esi_init();
X #endif
@@ -117,6 +123,10 @@
X #ifdef CONFIG_GIRBIL_DONGLE
X girbil_init();
X #endif
+#ifdef CONFIG_GIRBIL_DONGLE
+ litelink_init();
+#endif
+


X return 0;
X }
X

@@ -169,6 +179,8 @@
X /* Initialize timers */
X init_timer(&self->media_busy_timer);
X
+ self->lock = SPIN_LOCK_UNLOCKED;
+
X /* A pointer to the low level implementation */
X self->priv = priv;
X
@@ -200,7 +212,7 @@
X /* Open network device */
X dev_open(&self->netdev);
X
- MESSAGE("IrDA: Registred device %s\n", self->name);
+ MESSAGE("IrDA: Registered device %s\n", self->name);
X
X irda_device_set_media_busy(self, FALSE);
X
@@ -307,6 +319,8 @@
X */
X static void __irda_device_change_speed(struct irda_device *self, int speed)
X {
+ int n = 0;
+
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
X
@@ -314,22 +328,37 @@
X * Is is possible to change speed yet? Wait until the last byte
X * has been transmitted.
X */
- if (self->wait_until_sent) {
- self->wait_until_sent(self);
-
- if (self->dongle)
- self->dongle->change_speed(self, speed);
-
- if (self->change_speed) {
- self->change_speed(self, speed);
-
- /* Update the QoS value only */
- self->qos.baud_rate.value = speed;
+ if (!self->wait_until_sent) {
+ ERROR("IrDA: wait_until_sent() "
+ "has not implemented by the IrDA device driver!\n");
+ return;
+ }
+
+ /* Make sure all transmitted data has actually been sent */
+ self->wait_until_sent(self);
+
+ /* Make sure nobody tries to transmit during the speed change */
+ while (irda_lock((void *) &self->netdev.tbusy) == FALSE) {
+ WARNING(__FUNCTION__ "(), device locked!\n");


+ current->state = TASK_INTERRUPTIBLE;

+ schedule_timeout(MSECS_TO_JIFFIES(10));
+
+ if (n++ > 10) {
+ WARNING(__FUNCTION__ "(), breaking loop!\n");
+ break;
X }
- } else {
- WARNING("IrDA: wait_until_sent() "
- "has not implemented by the IrDA device driver!\n");
X }
+
+ if (self->dongle)
+ self->dongle->change_speed(self, speed);
+
+ if (self->change_speed) {
+ self->change_speed(self, speed);
+
+ /* Update the QoS value only */
+ self->qos.baud_rate.value = speed;
+ }
+ self->netdev.tbusy = FALSE;
X }
X
X /*
@@ -340,8 +369,6 @@
X */
X inline void irda_device_change_speed(struct irda_device *self, int speed)
X {
- DEBUG(4, __FUNCTION__ "()\n");
-
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
X
@@ -352,27 +379,27 @@
X
X inline int irda_device_is_media_busy( struct irda_device *self)
X {
- ASSERT( self != NULL, return FALSE;);
- ASSERT( self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+ ASSERT(self != NULL, return FALSE;);
+ ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
X
X return self->media_busy;
X }
X
X inline int irda_device_is_receiving( struct irda_device *self)
X {
- ASSERT( self != NULL, return FALSE;);
- ASSERT( self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+ ASSERT(self != NULL, return FALSE;);
+ ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
X
- if ( self->is_receiving)
- return self->is_receiving( self);
+ if (self->is_receiving)
+ return self->is_receiving(self);
X else
X return FALSE;
X }
X
-inline struct qos_info *irda_device_get_qos( struct irda_device *self)
+inline struct qos_info *irda_device_get_qos(struct irda_device *self)
X {
- ASSERT( self != NULL, return NULL;);
- ASSERT( self->magic == IRDA_DEVICE_MAGIC, return NULL;);
+ ASSERT(self != NULL, return NULL;);
+ ASSERT(self->magic == IRDA_DEVICE_MAGIC, return NULL;);
X
X return &self->qos;
X }
@@ -394,8 +421,6 @@
X {
X struct irda_device *self;
X
- DEBUG(4, __FUNCTION__ "()\n");
-
X ASSERT(dev != NULL, return -1;);
X
X self = (struct irda_device *) dev->priv;
@@ -467,6 +492,8 @@


X return 0;
X }
X
+

+#define SIOCSDONGLE SIOCDEVPRIVATE
X static int irda_device_net_ioctl(struct device *dev, /* ioctl device */
X struct ifreq *rq, /* Data passed */
X int cmd) /* Ioctl number */
@@ -577,6 +604,10 @@
X #endif
X break;
X #endif
+ case SIOCSDONGLE: /* Set dongle */
+ /* Initialize dongle */
+ irda_device_init_dongle(self, (int) rq->ifr_data);
+ break;
X default:
X ret = -EOPNOTSUPP;
X }
@@ -652,6 +683,11 @@
X ERROR("IrDA: Unable to find requested dongle\n");
X return;
X }
+
+ /* Check if we're already using a dongle */
+ if (self->dongle) {
+ self->dongle->close(self);
+ }
X
X /* Set the dongle to be used by this driver */
X self->dongle = node->dongle;
@@ -661,7 +697,7 @@
X node->dongle->qos_init(self, &self->qos);
X
X /* Reset dongle */
- node->dongle->reset(self, 0);
+ node->dongle->reset(self);
X
X /* Set to default baudrate */
X irda_device_change_speed(self, 9600);
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c
--- v2.3.5/linux/net/irda/irlan/irlan_client.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlan/irlan_client.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@


X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sun Aug 31 20:14:37 1997

- * Modified at: Tue May 11 00:22:39 1999
+ * Modified at: Mon May 31 14:19:34 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>
@@ -213,7 +213,7 @@
X {
X struct irlan_cb *self;
X
- DEBUG(4, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
X
X self = (struct irlan_cb *) instance;
X
@@ -222,6 +222,12 @@
X ASSERT(skb != NULL, return -1;);
X
X irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
+
+ /* Ready for a new command */
+ self->client.tx_busy = FALSE;
+
+ /* Check if we have some queued commands waiting to be sent */
+ irlan_run_ctrl_tx_queue(self);


X
X return 0;
X }

diff -u --recursive --new-file v2.3.5/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c
--- v2.3.5/linux/net/irda/irlan/irlan_client_event.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlan/irlan_client_event.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@


X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sun Aug 31 20:14:37 1997

- * Modified at: Thu May 6 13:42:38 1999
+ * Modified at: Fri May 14 23:08:15 1999


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

X *

X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>,

diff -u --recursive --new-file v2.3.5/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.5/linux/net/irda/irlan/irlan_common.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlan/irlan_common.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@


X * Status: Experimental.
X * Author: Dag Brattli <da...@cs.uit.no>
X * Created at: Sun Aug 31 20:14:37 1997

- * Modified at: Sun May 9 11:48:49 1999
+ * Modified at: Mon May 31 14:25:19 1999


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

X *
X * Copyright (c) 1997, 1999 Dag Brattli <da...@cs.uit.no>,
@@ -301,7 +301,9 @@
X init_timer(&self->client.kick_timer);
X
X hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
-
+
+ skb_queue_head_init(&self->client.txq);
+
X irlan_next_client_state(self, IRLAN_IDLE);
X irlan_next_provider_state(self, IRLAN_IDLE);


X
@@ -321,7 +323,7 @@

X */
X static void __irlan_close(struct irlan_cb *self)
X {
- DEBUG(0, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
X
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -423,8 +425,6 @@
X {
X struct irlan_cb *self;
X
- DEBUG(2, __FUNCTION__ "()\n");
-
X self = (struct irlan_cb *) instance;
X
X ASSERT(self != NULL, return;);
@@ -444,9 +444,15 @@
X */
X irlan_get_unicast_addr(self);
X irlan_open_unicast_addr(self);
+
+ /* Open broadcast and multicast filter by default */
+ irlan_set_broadcast_filter(self, TRUE);
+ irlan_set_multicast_filter(self, TRUE);
X
X /* Ready to transfer Ethernet frames */
X self->dev.tbusy = 0;
+
+ irlan_eth_send_gratuitous_arp(&self->dev);
X }
X
X /*
@@ -495,9 +501,6 @@
X break;
X }
X
- /* Stop IP from transmitting more packets */
- /* irlan_client_flow_indication(handle, FLOW_STOP, priv); */
-
X irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
X irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
X }
@@ -507,7 +510,7 @@
X struct notify_t notify;
X struct tsap_cb *tsap;
X
- DEBUG(0, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
X
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -522,7 +525,7 @@
X notify.udata_indication = irlan_eth_receive;
X notify.connect_indication = irlan_connect_indication;
X notify.connect_confirm = irlan_connect_confirm;
- notify.flow_indication = irlan_eth_flow_indication;
+ /*notify.flow_indication = irlan_eth_flow_indication;*/
X notify.disconnect_indication = irlan_disconnect_indication;
X notify.instance = self;
X strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
@@ -555,7 +558,6 @@
X irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
X irttp_close_tsap(self->tsap_data);
X self->tsap_data = NULL;
-
X }
X if (self->client.tsap_ctrl) {
X irttp_disconnect_request(self->client.tsap_ctrl, NULL,
@@ -608,15 +610,60 @@
X irias_add_string_attrib(obj, "Name", "Linux");
X #endif
X irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
- irias_add_integer_attrib(obj, "CompCnt", 2);
- irias_add_string_attrib(obj, "Comp#01", "PNP8294");
- irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+ irias_add_integer_attrib(obj, "CompCnt", 1);
+ if (self->provider.access_type == ACCESS_PEER)
+ irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+ else
+ irias_add_string_attrib(obj, "Comp#01", "PNP8294");
+
X irias_add_string_attrib(obj, "Manufacturer", "Linux-IrDA Project");
X irias_insert_object(obj);
X }
X }
X
X /*
+ * Function irlan_run_ctrl_tx_queue (self)
+ *
+ * Try to send the next command in the control transmit queue
+ *
+ */
+int irlan_run_ctrl_tx_queue(struct irlan_cb *self)


+{
+ struct sk_buff *skb;
+

+ if (irda_lock(&self->client.tx_busy) == FALSE)
+ return -EBUSY;
+
+ skb = skb_dequeue(&self->client.txq);
+ if (!skb) {
+ self->client.tx_busy = FALSE;
+ return 0;
+ }
+ if (self->client.tsap_ctrl == NULL) {
+ self->client.tx_busy = FALSE;
+ dev_kfree_skb(skb);


+ return -1;
+ }
+

+ return irttp_data_request(self->client.tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_ctrl_data_request (self, skb)
+ *
+ * This function makes sure that commands on the control channel is being
+ * sent in a command/response fashion
+ */
+void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
+{
+ /* Queue command */
+ skb_queue_tail(&self->client.txq, skb);
+
+ /* Try to send command */
+ irlan_run_ctrl_tx_queue(self);
+}
+
+/*
X * Function irlan_get_provider_info (self)
X *
X * Send Get Provider Information command to peer IrLAN layer
@@ -645,7 +692,8 @@
X frame[0] = CMD_GET_PROVIDER_INFO;
X frame[1] = 0x00; /* Zero parameters */
X
- irttp_data_request(self->client.tsap_ctrl, skb);
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -683,7 +731,8 @@
X
X /* self->use_udata = TRUE; */
X
- irttp_data_request(self->client.tsap_ctrl, skb);
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X void irlan_close_data_channel(struct irlan_cb *self)
@@ -696,6 +745,10 @@
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == IRLAN_MAGIC, return;);
X
+ /* Check if the TSAP is still there */
+ if (self->client.tsap_ctrl == NULL)
+ return;
+
X skb = dev_alloc_skb(64);
X if (!skb)
X return;


@@ -711,7 +764,8 @@
X

X irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
X
- irttp_data_request(self->client.tsap_ctrl, skb);
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -747,7 +801,8 @@
X irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
X irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
X
- irttp_data_request(self->client.tsap_ctrl, skb);
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -787,8 +842,9 @@
X irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
X else
X irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
-
- irttp_data_request(self->client.tsap_ctrl, skb);
+
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -826,8 +882,9 @@
X irlan_insert_string_param(skb, "FILTER_MODE", "ALL");
X else
X irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
-
- irttp_data_request(self->client.tsap_ctrl, skb);
+
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -864,7 +921,8 @@
X irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
X irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC");
X
- irttp_data_request(self->client.tsap_ctrl, skb);
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -899,7 +957,8 @@
X
X irlan_insert_string_param(skb, "MEDIA", "802.3");
X
- irttp_data_request(self->client.tsap_ctrl, skb);
+ /* irttp_data_request(self->client.tsap_ctrl, skb); */
+ irlan_ctrl_data_request(self, skb);
X }
X
X /*
@@ -1153,34 +1212,34 @@
X printk(KERN_INFO "Success\n");
X break;
X case 1:
- printk(KERN_WARNING "Insufficient resources\n");
+ WARNING("IrLAN: Insufficient resources\n");
X break;
X case 2:
- printk(KERN_WARNING "Invalid command format\n");
+ WARNING("IrLAN: Invalid command format\n");
X break;
X case 3:
- printk(KERN_WARNING "Command not supported\n");
+ WARNING("IrLAN: Command not supported\n");
X break;
X case 4:
- printk(KERN_WARNING "Parameter not supported\n");
+ WARNING("IrLAN: Parameter not supported\n");
X break;
X case 5:
- printk(KERN_WARNING "Value not supported\n");
+ WARNING("IrLAN: Value not supported\n");
X break;
X case 6:
- printk(KERN_WARNING "Not open\n");
+ WARNING("IrLAN: Not open\n");
X break;
X case 7:
- printk(KERN_WARNING "Authentication required\n");
+ WARNING("IrLAN: Authentication required\n");
X break;
X case 8:
- printk(KERN_WARNING "Invalid password\n");
+ WARNING("IrLAN: Invalid password\n");
X break;
X case 9:
- printk(KERN_WARNING "Protocol error\n");
+ WARNING("IrLAN: Protocol error\n");
X break;
X case 255:
- printk(KERN_WARNING "Asynchronous status\n");
+ WARNING("IrLAN: Asynchronous status\n");
X break;
X }
X }
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.3.5/linux/net/irda/irlan/irlan_eth.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlan/irlan_eth.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@


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

X * Created at: Thu Oct 15 08:37:58 1998
- * Modified at: Mon May 10 20:23:49 1999
+ * Modified at: Mon May 31 19:57:08 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>
@@ -50,7 +50,7 @@
X struct irmanager_event mgr_event;
X struct irlan_cb *self;
X
- DEBUG(0, __FUNCTION__"()\n");
+ DEBUG(2, __FUNCTION__"()\n");
X
X ASSERT(dev != NULL, return -1;);
X
@@ -66,7 +66,12 @@
X
X ether_setup(dev);
X
- dev->tx_queue_len = TTP_MAX_QUEUE;
+ /*
+ * Lets do all queueing in IrTTP instead of this device driver.
+ * Queueing here as well can introduce some strange latency
+ * problems, which we will avoid by setting the queue size to 0.
+ */
+ dev->tx_queue_len = 0;
X
X if (self->provider.access_type == ACCESS_DIRECT) {
X /*
@@ -110,7 +115,7 @@
X {
X struct irlan_cb *self;
X
- DEBUG(0, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
X
X ASSERT(dev != NULL, return -1;);
X
@@ -145,7 +150,7 @@
X {
X struct irlan_cb *self = (struct irlan_cb *) dev->priv;
X
- DEBUG(0, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
X

X /* Stop device */
X dev->tbusy = 1;

@@ -180,26 +185,16 @@
X int irlan_eth_xmit(struct sk_buff *skb, struct device *dev)
X {
X struct irlan_cb *self;
+ int ret;
X
X self = (struct irlan_cb *) dev->priv;
X
X ASSERT(self != NULL, return 0;);
X ASSERT(self->magic == IRLAN_MAGIC, return 0;);
X
- /* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE) {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- */
- int tickssofar = jiffies - dev->trans_start;
-
- if (tickssofar < 5)
- return -EBUSY;
-
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- }
+ /* Check if IrTTP can accept more frames */
+ if (dev->tbusy)
+ return -EBUSY;
X
X /* skb headroom large enough to contain all IrDA-headers? */
X if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
@@ -218,31 +213,30 @@
X }
X
X dev->trans_start = jiffies;
- self->stats.tx_packets++;
- self->stats.tx_bytes += skb->len;
X
X /* Now queue the packet in the transport layer */
X if (self->use_udata)
- irttp_udata_request(self->tsap_data, skb);
- 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;


-
- return 0;
- }

+ ret = irttp_udata_request(self->tsap_data, skb);
+ else
+ ret = irttp_data_request(self->tsap_data, skb);
+
+ if (ret < 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++;
+ } else {
+ self->stats.tx_packets++;
+ self->stats.tx_bytes += skb->len;
X }
- dev->tbusy = 0; /* Finished! */


X
X return 0;
X }

@@ -276,11 +270,11 @@
X skb->dev = &self->dev;
X skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
X
- netif_rx(skb); /* Eat it! */
-
X self->stats.rx_packets++;
X self->stats.rx_bytes += skb->len;
X
+ netif_rx(skb); /* Eat it! */
+

X return 0;
X }
X

@@ -295,8 +289,6 @@
X struct irlan_cb *self;


X struct device *dev;
X

- DEBUG(4, __FUNCTION__ "()\n");
-
X self = (struct irlan_cb *) instance;
X
X ASSERT(self != NULL, return;);
@@ -344,7 +336,7 @@
X * Send gratuitous ARP to announce that we have changed
X * hardware address, so that all peers updates their ARP tables
X */
-void irlan_etc_send_gratuitous_arp(struct device *dev)
+void irlan_eth_send_gratuitous_arp(struct device *dev)


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part25

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


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

X {


X struct in_device *in_dev;
X

@@ -375,16 +367,21 @@
X

X self = dev->priv;

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

- return;


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

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

X ASSERT(self->magic == IRLAN_MAGIC, return;);
X
- if (dev->flags&IFF_PROMISC) {
- /* Enable promiscuous mode */
- DEBUG(0, "Promiscous mode not implemented\n");
- /* outw(MULTICAST|PROMISC, ioaddr); */
+ /* Check if data channel has been connected yet */
+ if (self->client.state != IRLAN_DATA) {
+ DEBUG(1, __FUNCTION__ "(), delaying!\n");
+ return;
X }
+
+ if (dev->flags & IFF_PROMISC) {
+ /* Enable promiscuous mode */
+ WARNING("Promiscous mode not implemented by IrLAN!\n");
+ }
X else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
X /* Disable promiscuous mode, use normal mode. */
X DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
@@ -404,13 +401,10 @@
X irlan_set_multicast_filter(self, FALSE);
X }
X
- if (dev->flags & IFF_BROADCAST) {
- DEBUG(4, __FUNCTION__ "(), Setting broadcast filter\n");
+ if (dev->flags & IFF_BROADCAST)
X irlan_set_broadcast_filter(self, TRUE);
- } else {
- DEBUG(4, __FUNCTION__ "(), Clearing broadcast filter\n");
+ else
X irlan_set_broadcast_filter(self, FALSE);
- }
X }
X
X /*
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlan/irlan_filter.c linux/net/irda/irlan/irlan_filter.c
--- v2.3.5/linux/net/irda/irlan/irlan_filter.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlan/irlan_filter.c Mon Jun 7 16:18:58 1999


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

X * Created at: Fri Jan 29 11:16:38 1999
- * Modified at: Sat May 8 15:25:23 1999
+ * Modified at: Fri May 14 23:11:01 1999


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

X * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.

@@ -23,6 +23,7 @@
X ********************************************************************/
X
X #include <linux/skbuff.h>
+#include <linux/random.h>
X
X #include <net/irda/irlan_common.h>
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.3.5/linux/net/irda/irlap.c Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlap.c Mon Jun 7 16:18:58 1999
@@ -1,26 +1,31 @@
X /*********************************************************************
X *
X * Filename: irlap.c
- * Version: 0.9
- * Description: An IrDA LAP driver for Linux
- * Status: Stable.
+ * Version: 1.0
+ * Description: IrLAP implementation for Linux
+ * Status: Stable


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

X * Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Fri Apr 23 10:12:29 1999
+ * Modified at: Mon May 31 21:43:55 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, All Rights Reserved.
X *

- * This program is free software; you can redistribute iyt and/or
+ * This program is free software; you can redistribute it and/or
X * modify it under the terms of the GNU General Public License as
X * published by the Free Software Foundation; either version 2 of
X * the License, or (at your option) any later version.
- *
- * Neither Dag Brattli nor University of Tromsø admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
+ *
+ * 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 #include <linux/config.h>
@@ -60,23 +65,23 @@


X };
X
X #ifdef CONFIG_PROC_FS

-int irlap_proc_read( char *, char **, off_t, int, int);
+int irlap_proc_read(char *, char **, off_t, int, int);
X
X #endif /* CONFIG_PROC_FS */
X
-__initfunc(int irlap_init( void))
+__initfunc(int irlap_init(void))
X {
X /* Allocate master array */
- irlap = hashbin_new( HB_LOCAL);
- if ( irlap == NULL) {
- printk( KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n");
+ irlap = hashbin_new(HB_LOCAL);
+ if (irlap == NULL) {
+ printk(KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n");


X return -ENOMEM;
X }
X

X #ifdef CONFIG_IRDA_COMPRESSION
- irlap_compressors = hashbin_new( HB_LOCAL);
- if ( irlap_compressors == NULL) {
- printk( KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
+ irlap_compressors = hashbin_new(HB_LOCAL);
+ if (irlap_compressors == NULL) {
+ printk(KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
X return -ENOMEM;
X }
X #endif
@@ -86,12 +91,12 @@
X
X void irlap_cleanup(void)
X {
- ASSERT( irlap != NULL, return;);
+ ASSERT(irlap != NULL, return;);
X
- hashbin_delete( irlap, (FREE_FUNC) __irlap_close);
+ hashbin_delete(irlap, (FREE_FUNC) __irlap_close);
X
X #ifdef CONFIG_IRDA_COMPRESSION
- hashbin_delete( irlap_compressors, (FREE_FUNC) kfree);
+ hashbin_delete(irlap_compressors, (FREE_FUNC) kfree);
X #endif
X }
X
@@ -101,32 +106,32 @@
X * Initialize IrLAP layer
X *
X */
-struct irlap_cb *irlap_open( struct irda_device *irdev)
+struct irlap_cb *irlap_open(struct irda_device *irdev)
X {
X struct irlap_cb *self;
X
- DEBUG( 4, __FUNCTION__ "()\n");


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

- ASSERT( irdev != NULL, return NULL;);
- ASSERT( irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
+ ASSERT(irdev != NULL, return NULL;);
+ ASSERT(irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
X
X /* Initialize the irlap structure. */
- self = kmalloc( sizeof( struct irlap_cb), GFP_KERNEL);


- if ( self == NULL)

+ self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
+ if (self == NULL)
X return NULL;
X
- memset( self, 0, sizeof(struct irlap_cb));
+ memset(self, 0, sizeof(struct irlap_cb));
X self->magic = LAP_MAGIC;
X
X /* Make a binding between the layers */
X self->irdev = irdev;
X self->netdev = &irdev->netdev;
X
- irlap_next_state( self, LAP_OFFLINE);
+ irlap_next_state(self, LAP_OFFLINE);
X
X /* Initialize transmitt queue */
- skb_queue_head_init( &self->tx_list);
- skb_queue_head_init( &self->wx_list);
+ skb_queue_head_init(&self->tx_list);
+ skb_queue_head_init(&self->wx_list);
X
X /* My unique IrLAP device address! */
X get_random_bytes(&self->saddr, sizeof(self->saddr));
@@ -140,21 +145,21 @@
X self->caddr &= 0xfe;
X }
X
- init_timer( &self->slot_timer);
- init_timer( &self->query_timer);
- init_timer( &self->discovery_timer);
- init_timer( &self->final_timer);
- init_timer( &self->poll_timer);
- init_timer( &self->wd_timer);
- init_timer( &self->backoff_timer);
+ init_timer(&self->slot_timer);
+ init_timer(&self->query_timer);
+ init_timer(&self->discovery_timer);
+ init_timer(&self->final_timer);
+ init_timer(&self->poll_timer);
+ init_timer(&self->wd_timer);
+ init_timer(&self->backoff_timer);
X
- irlap_apply_default_connection_parameters( self);
+ irlap_apply_default_connection_parameters(self);
X
- irlap_next_state( self, LAP_NDM);
+ irlap_next_state(self, LAP_NDM);
X
- hashbin_insert( irlap, (QUEUE *) self, self->saddr, NULL);
+ hashbin_insert(irlap, (QUEUE *) self, self->saddr, NULL);
X
- irlmp_register_link( self, self->saddr, &self->notify);
+ irlmp_register_link(self, self->saddr, &self->notify);
X
X return self;
X }
@@ -165,26 +170,26 @@
X * Remove IrLAP and all allocated memory. Stop any pending timers.
X *
X */
-static void __irlap_close( struct irlap_cb *self)
+static void __irlap_close(struct irlap_cb *self)
X {
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X /* Stop timers */
- del_timer( &self->slot_timer);
- del_timer( &self->query_timer);
- del_timer( &self->discovery_timer);
- del_timer( &self->final_timer);
- del_timer( &self->poll_timer);
- del_timer( &self->wd_timer);
- del_timer( &self->backoff_timer);
+ del_timer(&self->slot_timer);
+ del_timer(&self->query_timer);
+ del_timer(&self->discovery_timer);
+ del_timer(&self->final_timer);
+ del_timer(&self->poll_timer);
+ del_timer(&self->wd_timer);
+ del_timer(&self->backoff_timer);
X
- irlap_flush_all_queues( self);
+ irlap_flush_all_queues(self);
X
X self->irdev = NULL;
X self->magic = 0;
X
- kfree( self);
+ kfree(self);
X }
X
X /*
@@ -193,27 +198,27 @@
X * Remove IrLAP instance
X *
X */
-void irlap_close( struct irlap_cb *self)
+void irlap_close(struct irlap_cb *self)
X {
X struct irlap_cb *lap;
X
- DEBUG( 4, __FUNCTION__ "()\n");


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

- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
- irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+ irlap_disconnect_indication(self, LAP_DISC_INDICATION);
X
X irlmp_unregister_link(self->saddr);
X self->notify.instance = NULL;
X
X /* Be sure that we manage to remove ourself from the hash */
- lap = hashbin_remove( irlap, self->saddr, NULL);
- if ( !lap) {
- DEBUG( 1, __FUNCTION__ "(), Didn't find myself!\n");
+ lap = hashbin_remove(irlap, self->saddr, NULL);
+ if (!lap) {
+ DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
X return;
X }
- __irlap_close( lap);
+ __irlap_close(lap);
X }
X
X /*
@@ -243,7 +248,7 @@
X */
X void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb)
X {
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
X
X irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
X }
@@ -324,23 +329,23 @@
X * Received some data that was sent unreliable
X *
X */
-void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_unit_data_indication(struct irlap_cb *self, struct sk_buff *skb)
X {
- DEBUG( 1, __FUNCTION__ "()\n");
+ DEBUG(1, __FUNCTION__ "()\n");
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
X
X /* Hide LAP header from IrLMP layer */
- skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+ skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
X
X #ifdef CONFIG_IRDA_COMPRESSION
- if ( self->qos_tx.compression.value) {
+ if (self->qos_tx.compression.value) {
X
- skb = irlap_decompress_frame( self, skb);
- if ( !skb) {
- DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
+ skb = irlap_decompress_frame(self, skb);
+ if (!skb) {
+ DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
X return;
X }
X }
@@ -354,40 +359,35 @@
X * Queue data for transmission, must wait until XMIT state
X *
X */
-inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb,
+inline void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
X int reliable)
X {
- DEBUG( 4, __FUNCTION__ "()\n");
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
-
- DEBUG( 4, __FUNCTION__ "(), tx_list=%d\n",
- skb_queue_len( &self->tx_list));
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
X
X #ifdef CONFIG_IRDA_COMPRESSION
- if ( self->qos_tx.compression.value) {
- skb = irlap_compress_frame( self, skb);
- if ( !skb) {
- DEBUG( 1, __FUNCTION__ "(), Compress error!\n");
+ if (self->qos_tx.compression.value) {
+ skb = irlap_compress_frame(self, skb);
+ if (!skb) {
+ DEBUG(1, __FUNCTION__ "(), Compress error!\n");
X return;
X }
X }
X #endif
X
- ASSERT( skb_headroom( skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
- return;);
- skb_push( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+ ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ return;);
+ skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
X
X /*
X * Must set frame format now so that the rest of the code knows
X * if its dealing with an I or an UI frame
X */
- if ( reliable)
+ if (reliable)
X skb->data[1] = I_FRAME;
X else {
- DEBUG( 4, __FUNCTION__ "(), queueing unreliable frame\n");
+ DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
X skb->data[1] = UI_FRAME;
X }
X
@@ -395,20 +395,20 @@
X * Send event if this frame only if we are in the right state
X * FIXME: udata should be sent first! (skb_queue_head?)
X */
- if (( self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
+ if ((self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
X /*
X * Check if the transmit queue contains some unsent frames,
X * and if so, make sure they are sent first
X */
- if ( !skb_queue_empty( &self->tx_list)) {
- skb_queue_tail( &self->tx_list, skb);
- skb = skb_dequeue( &self->tx_list);
+ if (!skb_queue_empty(&self->tx_list)) {
+ skb_queue_tail(&self->tx_list, skb);
+ skb = skb_dequeue(&self->tx_list);
X
- ASSERT( skb != NULL, return;);
+ ASSERT(skb != NULL, return;);
X }
- irlap_do_event( self, SEND_I_CMD, skb, NULL);
+ irlap_do_event(self, SEND_I_CMD, skb, NULL);
X } else
- skb_queue_tail( &self->tx_list, skb);
+ skb_queue_tail(&self->tx_list, skb);
X }
X
X /*
@@ -444,33 +444,33 @@
X * Disconnect request from other device
X *
X */
-void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason)
+void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
X {
- DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]);
+ DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]);
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X #ifdef CONFIG_IRDA_COMPRESSION
- irda_free_compression( self);
+ irda_free_compression(self);
X #endif
X /* Flush queues */
- irlap_flush_all_queues( self);
+ irlap_flush_all_queues(self);
X
- switch( reason) {
+ switch(reason) {
X case LAP_RESET_INDICATION:
- DEBUG( 1, __FUNCTION__ "(), Sending reset request!\n");
- irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+ DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
+ irlap_do_event(self, RESET_REQUEST, NULL, NULL);
X break;
X case LAP_NO_RESPONSE: /* FALLTROUGH */
X case LAP_DISC_INDICATION: /* FALLTROUGH */
X case LAP_FOUND_NONE: /* FALLTROUGH */
X case LAP_MEDIA_BUSY:
- irlmp_link_disconnect_indication( self->notify.instance,
+ irlmp_link_disconnect_indication(self->notify.instance,
X self, reason, NULL);
X break;
X default:
- DEBUG( 1, __FUNCTION__ "(), Reason %d not implemented!\n",
+ DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n",
X reason);
X }
X }
@@ -485,22 +485,22 @@
X {
X struct irlap_info info;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( discovery != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(discovery != NULL, return;);
X
- DEBUG( 4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
+ DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
X
- ASSERT(( discovery->nslots == 1) || ( discovery->nslots == 6) ||
- ( discovery->nslots == 8) || ( discovery->nslots == 16),
+ ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
+ (discovery->nslots == 8) || (discovery->nslots == 16),
X return;);
X
X /*
X * Discovery is only possible in NDM mode
X */
- if ( self->state == LAP_NDM) {
- ASSERT( self->discovery_log == NULL, return;);
- self->discovery_log= hashbin_new( HB_LOCAL);
+ if (self->state == LAP_NDM) {
+ ASSERT(self->discovery_log == NULL, return;);
+ self->discovery_log= hashbin_new(HB_LOCAL);
X
X info.S = discovery->nslots; /* Number of slots */
X info.s = 0; /* Current slot */
@@ -526,11 +526,11 @@
X
X self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
X
- irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info);
+ irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
X } else {
- DEBUG( 4, __FUNCTION__
+ DEBUG(4, __FUNCTION__
X "(), discovery only possible in NDM mode\n");
- irlap_discovery_confirm( self, NULL);
+ irlap_discovery_confirm(self, NULL);
X }
X }


X
@@ -540,12 +540,12 @@

X * A device has been discovered in front of this station, we
X * report directly to LMP.
X */
-void irlap_discovery_confirm( struct irlap_cb *self, hashbin_t *discovery_log)
+void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log)
X {
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
- ASSERT( self->notify.instance != NULL, return;);
+ ASSERT(self->notify.instance != NULL, return;);
X
X /*
X * Check for successful discovery, since we are then allowed to clear
@@ -556,7 +556,7 @@
X irda_device_set_media_busy(self->irdev, FALSE);
X
X /* Inform IrLMP */
- irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
+ irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
X
X /*
X * IrLMP has now the responsibilities for the discovery_log
@@ -572,13 +572,13 @@
X */
X void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery)
X {
- DEBUG( 4, __FUNCTION__ "()\n");


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

- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( discovery != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(discovery != NULL, return;);
X
- ASSERT( self->notify.instance != NULL, return;);
+ ASSERT(self->notify.instance != NULL, return;);
X
X irlmp_link_discovery_indication(self->notify.instance, discovery);
X }
@@ -591,12 +591,12 @@
X */
X void irlap_status_indication(int quality_of_link)
X {
- switch( quality_of_link) {
+ switch(quality_of_link) {
X case STATUS_NO_ACTIVITY:
- printk( KERN_INFO "IrLAP, no activity on link!\n");
+ printk(KERN_INFO "IrLAP, no activity on link!\n");
X break;
X case STATUS_NOISY:
- printk( KERN_INFO "IrLAP, noisy link!\n");
+ printk(KERN_INFO "IrLAP, noisy link!\n");
X break;
X default:
X break;
@@ -610,17 +610,17 @@
X *
X *
X */
-void irlap_reset_indication( struct irlap_cb *self)
+void irlap_reset_indication(struct irlap_cb *self)
X {
- DEBUG( 1, __FUNCTION__ "()\n");
+ DEBUG(1, __FUNCTION__ "()\n");
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
- if ( self->state == LAP_RESET_WAIT)
- irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+ if (self->state == LAP_RESET_WAIT)
+ irlap_do_event(self, RESET_REQUEST, NULL, NULL);
X else
- irlap_do_event( self, RESET_RESPONSE, NULL, NULL);
+ irlap_do_event(self, RESET_RESPONSE, NULL, NULL);
X }
X
X /*
@@ -631,7 +631,7 @@
X */
X void irlap_reset_confirm(void)
X {
- DEBUG( 1, __FUNCTION__ "()\n");
+ DEBUG(1, __FUNCTION__ "()\n");
X }
X
X /*
@@ -641,15 +641,15 @@
X * S = Number of slots (0 -> S-1)
X * s = Current slot
X */
-int irlap_generate_rand_time_slot( int S, int s)
+int irlap_generate_rand_time_slot(int S, int s)
X {
X int slot;
X
- ASSERT(( S - s) > 0, return 0;);
+ ASSERT((S - s) > 0, return 0;);
X
X slot = s + jiffies % (S-s);
X
- ASSERT(( slot >= s) || ( slot < S), return 0;);
+ ASSERT((slot >= s) || (slot < S), return 0;);
X
X return slot;
X }
@@ -661,51 +661,51 @@
X * not intuitive and you should not try to change it. If you think it
X * contains bugs, please mail a patch to the author instead.
X */
-void irlap_update_nr_received( struct irlap_cb *self, int nr)
+void irlap_update_nr_received(struct irlap_cb *self, int nr)
X {
X struct sk_buff *skb = NULL;
X int count = 0;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X /*
X * Remove all the ack-ed frames from the window queue.
X */
X
- DEBUG( 4, "--> wx_list=%d, va=%d, nr=%d\n",
- skb_queue_len( &self->wx_list), self->va, nr);
+ DEBUG(4, "--> wx_list=%d, va=%d, nr=%d\n",
+ skb_queue_len(&self->wx_list), self->va, nr);
X
X /*
X * Optimize for the common case. It is most likely that the receiver
X * will acknowledge all the frames we have sent! So in that case we
X * delete all frames stored in window.
X */
- if ( nr == self->vs) {
- while (( skb = skb_dequeue( &self->wx_list)) != NULL) {
+ if (nr == self->vs) {
+ while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
X dev_kfree_skb(skb);
X }
X /* The last acked frame is the next to send minus one */
X self->va = nr - 1;
X } else {
X /* Remove all acknowledged frames in current window */
- while (( skb_peek( &self->wx_list) != NULL) &&
- ((( self->va+1) % 8) != nr))
+ while ((skb_peek(&self->wx_list) != NULL) &&
+ (((self->va+1) % 8) != nr))
X {
- skb = skb_dequeue( &self->wx_list);
+ skb = skb_dequeue(&self->wx_list);
X dev_kfree_skb(skb);
X
X self->va = (self->va + 1) % 8;
X count++;
X }
X
- DEBUG( 4, "irlap_update_nr_received(), removed %d\n", count);
- DEBUG( 4, "wx_list=%d, va=%d, nr=%d -->\n",
- skb_queue_len( &self->wx_list), self->va, nr);
+ DEBUG(4, "irlap_update_nr_received(), removed %d\n", count);
+ DEBUG(4, "wx_list=%d, va=%d, nr=%d -->\n",
+ skb_queue_len(&self->wx_list), self->va, nr);
X }
X
X /* Advance window */
- self->window = self->window_size - skb_queue_len( &self->wx_list);
+ self->window = self->window_size - skb_queue_len(&self->wx_list);
X }
X
X /*
@@ -713,14 +713,14 @@
X *
X * Validate the next to send (ns) field from received frame.
X */
-int irlap_validate_ns_received( struct irlap_cb *self, int ns)
+int irlap_validate_ns_received(struct irlap_cb *self, int ns)
X {
- ASSERT( self != NULL, return -ENODEV;);
- ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+ ASSERT(self != NULL, return -ENODEV;);
+ ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
X
X /* ns as expected? */
- if ( ns == self->vr) {
- DEBUG( 4, __FUNCTION__ "(), expected!\n");
+ if (ns == self->vr) {
+ DEBUG(4, __FUNCTION__ "(), expected!\n");
X return NS_EXPECTED;
X }
X /*
@@ -737,14 +737,14 @@
X * Validate the next to receive (nr) field from received frame.
X *
X */
-int irlap_validate_nr_received( struct irlap_cb *self, int nr)
+int irlap_validate_nr_received(struct irlap_cb *self, int nr)
X {
- ASSERT( self != NULL, return -ENODEV;);
- ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+ ASSERT(self != NULL, return -ENODEV;);
+ ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
X
X /* nr as expected? */
- if ( nr == self->vs) {
- DEBUG( 4, __FUNCTION__ "(), expected!\n");
+ if (nr == self->vs) {
+ DEBUG(4, __FUNCTION__ "(), expected!\n");
X return NR_EXPECTED;
X }
X
@@ -752,11 +752,11 @@
X * unexpected nr? (but within current window), first we check if the
X * ns numbers of the frames in the current window wrap.
X */
- if ( self->va < self->vs) {
- if (( nr >= self->va) && ( nr <= self->vs))
+ if (self->va < self->vs) {
+ if ((nr >= self->va) && (nr <= self->vs))
X return NR_UNEXPECTED;
X } else {
- if (( nr >= self->va) || ( nr <= self->vs))
+ if ((nr >= self->va) || (nr <= self->vs))
X return NR_UNEXPECTED;
X }
X
@@ -770,12 +770,12 @@
X * Initialize the connection state parameters
X *
X */
-void irlap_initiate_connection_state( struct irlap_cb *self)
+void irlap_initiate_connection_state(struct irlap_cb *self)
X {
- DEBUG( 4, __FUNCTION__ "()\n");


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

- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X /* Next to send and next to receive */
X self->vs = self->vr = 0;
@@ -829,24 +829,24 @@
X * Flush all queues
X *
X */
-void irlap_flush_all_queues( struct irlap_cb *self)
+void irlap_flush_all_queues(struct irlap_cb *self)
X {


X struct sk_buff* skb;
X

- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X /* Free transmission queue */
- while (( skb = skb_dequeue( &self->tx_list)) != NULL)
- dev_kfree_skb( skb);
+ while ((skb = skb_dequeue(&self->tx_list)) != NULL)
+ dev_kfree_skb(skb);
X
X /* Free sliding window buffered packets */
- while (( skb = skb_dequeue( &self->wx_list)) != NULL)
- dev_kfree_skb( skb);
+ while ((skb = skb_dequeue(&self->wx_list)) != NULL)
+ dev_kfree_skb(skb);
X
X #ifdef CONFIG_IRDA_RECYCLE_RR
- if ( self->recycle_rr_skb) {
- dev_kfree_skb( self->recycle_rr_skb);
+ if (self->recycle_rr_skb) {
+ dev_kfree_skb(self->recycle_rr_skb);
X self->recycle_rr_skb = NULL;
X }
X #endif
@@ -866,7 +866,7 @@
X ASSERT(self->magic == LAP_MAGIC, return;);
X
X if (!self->irdev) {
- DEBUG( 1, __FUNCTION__ "(), driver missing!\n");
+ DEBUG(1, __FUNCTION__ "(), driver missing!\n");
X return;
X }


X
@@ -883,8 +883,8 @@

X __u8 mask; /* Current bit tested */
X int i;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
X /*
X * Find out which compressors we support. We do this be checking that
@@ -892,24 +892,24 @@
X * actually been loaded. Ths is sort of hairy code but that is what
X * you get when you do a little bit flicking :-)
X */
- DEBUG( 4, __FUNCTION__ "(), comp bits 0x%02x\n",
+ DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n",
X self->qos_rx.compression.bits);
X mask = 0x80; /* Start with testing MSB */
- for ( i=0;i<8;i++) {
- DEBUG( 4, __FUNCTION__ "(), testing bit %d\n", 8-i);
- if ( self->qos_rx.compression.bits & mask) {
- DEBUG( 4, __FUNCTION__ "(), bit %d is set by defalt\n",
+ for (i=0;i<8;i++) {
+ DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
+ if (self->qos_rx.compression.bits & mask) {
+ DEBUG(4, __FUNCTION__ "(), bit %d is set by defalt\n",
X 8-i);
- comp = hashbin_find( irlap_compressors,
+ comp = hashbin_find(irlap_compressors,
X compression[ msb_index(mask)],
X NULL);
- if ( !comp) {
+ if (!comp) {
X /* Protocol not supported, so clear the bit */
- DEBUG( 4, __FUNCTION__ "(), Compression "
+ DEBUG(4, __FUNCTION__ "(), Compression "
X "protocol %d has not been loaded!\n",
X compression[msb_index(mask)]);
X self->qos_rx.compression.bits &= ~mask;
- DEBUG( 4, __FUNCTION__
+ DEBUG(4, __FUNCTION__
X "(), comp bits 0x%02x\n",
X self->qos_rx.compression.bits);
X }
@@ -931,20 +931,20 @@
X void irlap_init_qos_capabilities(struct irlap_cb *self,
X struct qos_info *qos_user)
X {
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( self->irdev != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(self->irdev != NULL, return;);
X
X /* Start out with the maximum QoS support possible */
- irda_init_max_qos_capabilies( &self->qos_rx);
+ irda_init_max_qos_capabilies(&self->qos_rx);
X
X #ifdef CONFIG_IRDA_COMPRESSION
- irlap_init_comp_qos_capabilities( self);
+ irlap_init_comp_qos_capabilities(self);
X #endif
X
X /* Apply drivers QoS capabilities */
- irda_qos_compute_intersection( &self->qos_rx,
- irda_device_get_qos( self->irdev));
+ irda_qos_compute_intersection(&self->qos_rx,
+ irda_device_get_qos(self->irdev));
X
X /*
X * Check for user supplied QoS parameters. The service user is only
@@ -952,17 +952,17 @@
X * user may not have set all of them.
X */
X if (qos_user) {
- DEBUG( 1, __FUNCTION__ "(), Found user specified QoS!\n");
+ DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
X
- if ( qos_user->baud_rate.bits)
+ if (qos_user->baud_rate.bits)
X self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
X
- if ( qos_user->max_turn_time.bits)
+ if (qos_user->max_turn_time.bits)
X self->qos_rx.max_turn_time.bits &= qos_user->max_turn_time.bits;
- if ( qos_user->data_size.bits)
+ if (qos_user->data_size.bits)
X self->qos_rx.data_size.bits &= qos_user->data_size.bits;
X
- if ( qos_user->link_disc_time.bits)
+ if (qos_user->link_disc_time.bits)
X self->qos_rx.link_disc_time.bits &= qos_user->link_disc_time.bits;
X #ifdef CONFIG_IRDA_COMPRESSION
X self->qos_rx.compression.bits &= qos_user->compression.bits;
@@ -984,7 +984,7 @@
X /* Set disconnect time */
X self->qos_rx.link_disc_time.bits &= 0x07;
X
- irda_qos_bits_to_value( &self->qos_rx);
+ irda_qos_bits_to_value(&self->qos_rx);
X }
X
X /*
@@ -993,14 +993,14 @@
X * Use the default connection and transmission parameters
X *
X */
-void irlap_apply_default_connection_parameters( struct irlap_cb *self)
+void irlap_apply_default_connection_parameters(struct irlap_cb *self)
X {
- DEBUG( 4, __FUNCTION__ "()\n");


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

- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
- irlap_change_speed( self, 9600);
+ irlap_change_speed(self, 9600);
X
X /* Default value in NDM */
X self->bofs_count = 11;
@@ -1028,12 +1028,12 @@
X void irlap_apply_connection_parameters(struct irlap_cb *self,
X struct qos_info *qos)
X {
- DEBUG( 4, __FUNCTION__ "()\n");


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

- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
X
- irlap_change_speed( self, qos->baud_rate.value);
+ irlap_change_speed(self, qos->baud_rate.value);
X
X self->window_size = qos->window_size.value;
X self->window = qos->window_size.value;
@@ -1045,7 +1045,7 @@
X */
X self->window_bytes = qos->baud_rate.value
X * qos->max_turn_time.value / 10000;
- DEBUG( 4, "Setting window_bytes = %d\n", self->window_bytes);
+ DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
X
X /*
X * Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to
@@ -1058,10 +1058,10 @@
X else
X self->N1 = 3000 / qos->max_turn_time.value;
X
- DEBUG( 4, "Setting N1 = %d\n", self->N1);
+ DEBUG(4, "Setting N1 = %d\n", self->N1);
X
X self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
- DEBUG( 4, "Setting N2 = %d\n", self->N2);
+ DEBUG(4, "Setting N2 = %d\n", self->N2);
X
X /*
X * Initialize timeout values, some of the rules are listed on
@@ -1072,11 +1072,11 @@
X self->wd_timeout = self->poll_timeout * 2;
X
X #ifdef CONFIG_IRDA_COMPRESSION
- if ( qos->compression.value) {
- DEBUG( 1, __FUNCTION__ "(), Initializing compression\n");
- irda_set_compression( self, qos->compression.value);
+ if (qos->compression.value) {
+ DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
+ irda_set_compression(self, qos->compression.value);
X
- irlap_compressor_init( self, 0);
+ irlap_compressor_init(self, 0);
X }
X #endif


X }
@@ -1088,7 +1088,7 @@

X * Give some info to the /proc file system
X *
X */
-int irlap_proc_read( char *buf, char **start, off_t offset, int len,
+int irlap_proc_read(char *buf, char **start, off_t offset, int len,
X int unused)
X {
X struct irlap_cb *self;
@@ -1100,81 +1100,81 @@
X
X len = 0;
X
- self = (struct irlap_cb *) hashbin_get_first( irlap);
- while ( self != NULL) {
- ASSERT( self != NULL, return -ENODEV;);
- ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+ self = (struct irlap_cb *) hashbin_get_first(irlap);
+ while (self != NULL) {
+ ASSERT(self != NULL, return -ENODEV;);
+ ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
X
- len += sprintf( buf+len, "irlap%d <-> %s ",
+ len += sprintf(buf+len, "irlap%d <-> %s ",
X i++, self->irdev->name);
- len += sprintf( buf+len, "state: %s\n",
+ len += sprintf(buf+len, "state: %s\n",
X irlap_state[ self->state]);
X
- len += sprintf( buf+len, " caddr: %#02x, ", self->caddr);
- len += sprintf( buf+len, "saddr: %#08x, ", self->saddr);
- len += sprintf( buf+len, "daddr: %#08x\n", self->daddr);
+ len += sprintf(buf+len, " caddr: %#02x, ", self->caddr);
+ len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
+ len += sprintf(buf+len, "daddr: %#08x\n", self->daddr);
X
- len += sprintf( buf+len, " win size: %d, ",
+ len += sprintf(buf+len, " win size: %d, ",
X self->window_size);
- len += sprintf( buf+len, "win: %d, ", self->window);
- len += sprintf( buf+len, "win bytes: %d, ", self->window_bytes);
- len += sprintf( buf+len, "bytes left: %d\n", self->bytes_left);
-
- len += sprintf( buf+len, " tx queue len: %d ",
- skb_queue_len( &self->tx_list));
- len += sprintf( buf+len, "win queue len: %d ",
- skb_queue_len( &self->wx_list));
- len += sprintf( buf+len, "rbusy: %s\n", self->remote_busy ?
+ len += sprintf(buf+len, "win: %d, ", self->window);
+ len += sprintf(buf+len, "win bytes: %d, ", self->window_bytes);
+ len += sprintf(buf+len, "bytes left: %d\n", self->bytes_left);
+
+ len += sprintf(buf+len, " tx queue len: %d ",
+ skb_queue_len(&self->tx_list));
+ len += sprintf(buf+len, "win queue len: %d ",
+ skb_queue_len(&self->wx_list));
+ len += sprintf(buf+len, "rbusy: %s\n", self->remote_busy ?
X "TRUE" : "FALSE");
X
- len += sprintf( buf+len, " retrans: %d ", self->retry_count);
- len += sprintf( buf+len, "vs: %d ", self->vs);
- len += sprintf( buf+len, "vr: %d ", self->vr);
- len += sprintf( buf+len, "va: %d\n", self->va);
+ len += sprintf(buf+len, " retrans: %d ", self->retry_count);
+ len += sprintf(buf+len, "vs: %d ", self->vs);
+ len += sprintf(buf+len, "vr: %d ", self->vr);
+ len += sprintf(buf+len, "va: %d\n", self->va);
X
- len += sprintf( buf+len, " qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
+ len += sprintf(buf+len, " qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
X
- len += sprintf( buf+len, " tx\t%d\t",
+ len += sprintf(buf+len, " tx\t%d\t",
X self->qos_tx.baud_rate.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_tx.max_turn_time.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_tx.data_size.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_tx.window_size.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_tx.additional_bofs.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_tx.min_turn_time.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_tx.link_disc_time.value);
X #ifdef CONFIG_IRDA_COMPRESSION
- len += sprintf( buf+len, "%d",
+ len += sprintf(buf+len, "%d",
X self->qos_tx.compression.value);
X #endif


- len += sprintf( buf+len, "\n");
+ len += sprintf(buf+len, "\n");
X

- len += sprintf( buf+len, " rx\t%d\t",
+ len += sprintf(buf+len, " rx\t%d\t",
X self->qos_rx.baud_rate.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_rx.max_turn_time.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_rx.data_size.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_rx.window_size.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_rx.additional_bofs.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_rx.min_turn_time.value);
- len += sprintf( buf+len, "%d\t",
+ len += sprintf(buf+len, "%d\t",
X self->qos_rx.link_disc_time.value);
X #ifdef CONFIG_IRDA_COMPRESSION
- len += sprintf( buf+len, "%d",
+ len += sprintf(buf+len, "%d",
X self->qos_rx.compression.value);
X #endif


- len += sprintf( buf+len, "\n");
+ len += sprintf(buf+len, "\n");
X

- self = (struct irlap_cb *) hashbin_get_next( irlap);
+ self = (struct irlap_cb *) hashbin_get_next(irlap);
X }
X restore_flags(flags);
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.3.5/linux/net/irda/irlap_event.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlap_event.c Mon Jun 7 16:18:58 1999


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

X * Created at: Sat Aug 16 00:59:29 1997
- * Modified at: Sun May 9 22:44:32 1999
+ * Modified at: Mon May 31 21:55:42 1999


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

@@ -209,8 +209,8 @@
X * Rushes through the state machine without any delay. If state == XMIT
X * then send queued data frames.
X */
-void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event,
- struct sk_buff *skb, struct irlap_info *info)
+void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
+ struct sk_buff *skb, struct irlap_info *info)
X {
X int ret;
X
@@ -218,7 +218,7 @@
X return;
X
X DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n",
- irlap_event[ event], irlap_state[ self->state]);
+ irlap_event[event], irlap_state[self->state]);
X
X ret = (*state[ self->state]) (self, event, skb, info);
X
@@ -236,13 +236,12 @@
X if (skb_queue_len(&self->tx_list)) {
X /* Try to send away all queued data frames */
X while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
- ret = (*state[ self->state])(self, SEND_I_CMD,
- skb, NULL);
+ ret = (*state[self->state])(self, SEND_I_CMD,
+ skb, NULL);
X if ( ret == -EPROTO)
X break; /* Try again later! */
X }
X } else if (self->disconnect_pending) {
- DEBUG(0, __FUNCTION__ "(), disconnecting!\n");
X self->disconnect_pending = FALSE;
X
X ret = (*state[self->state])(self, DISCONNECT_REQUEST,
@@ -761,36 +760,30 @@
X * stations.
X *
X */
-static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event,
- struct sk_buff *skb, struct irlap_info *info)
+static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ struct sk_buff *skb, struct irlap_info *info)
X {
X int ret = 0;
X
- ASSERT( self != NULL, return -ENODEV;);
- ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
-
- DEBUG( 4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d",
- irlap_event[ event], self->vs, self->vr);
+ DEBUG(4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d",
+ irlap_event[event], self->vs, self->vr);
X
X switch (event) {
X case SEND_I_CMD:
- ASSERT( skb != NULL, return -1;);
- DEBUG( 4, __FUNCTION__ "(), Window=%d\n", self->window);
-
X /*
X * Only send frame if send-window > 0.
X */
- if (( self->window > 0) && ( !self->remote_busy)) {
+ if ((self->window > 0) && (!self->remote_busy)) {
X
X /*
X * Test if we have transmitted more bytes over the
X * link than its possible to do with the current
X * speed and turn-around-time.
X */
- if (( skb->len+self->bofs_count) > self->bytes_left) {
- DEBUG( 4, __FUNCTION__ "(), Not allowed to "
- "transmit more bytes!\n");
- skb_queue_head( &self->tx_list, skb);
+ if ((skb->len+self->bofs_count) > self->bytes_left) {
+ DEBUG(4, __FUNCTION__ "(), Not allowed to "
+ "transmit more bytes!\n");
+ skb_queue_head(&self->tx_list, skb);
X
X /*
X * We should switch state to LAP_NRM_P, but
@@ -802,7 +795,7 @@
X */
X return -EPROTO;
X }
- self->bytes_left -= ( skb->len + self->bofs_count);
+ self->bytes_left -= (skb->len + self->bofs_count);
X
X /*
X * Send data with poll bit cleared only if window > 1
@@ -811,11 +804,9 @@
X if (( self->window > 1) &&
X skb_queue_len( &self->tx_list) > 0)
X {
- DEBUG( 4, __FUNCTION__ "(), window > 1\n");
X irlap_send_data_primary( self, skb);
X irlap_next_state( self, LAP_XMIT_P);
X } else {
- DEBUG( 4, __FUNCTION__ "(), window <= 1\n");
X irlap_send_data_primary_poll( self, skb);
X irlap_next_state( self, LAP_NRM_P);
X
@@ -933,9 +924,6 @@
X int ns_status;
X int nr_status;
X
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
-
X switch (event) {
X case RECV_I_RSP: /* Optimize for the common case */
X /* FIXME: must check for remote_busy below */
@@ -947,7 +935,6 @@
X */
X self->fast_RR = FALSE;
X #endif
-
X ASSERT( info != NULL, return -1;);
X
X ns_status = irlap_validate_ns_received(self, info->ns);
@@ -1141,13 +1128,6 @@
X }
X break;
X case RECV_RR_RSP:
- DEBUG(4, __FUNCTION__ "(), RECV_RR_FRAME: "
- "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n",
- self->retry_count, info->nr, self->va, self->vs,
- self->vr);
-
- ASSERT(info != NULL, return -1;);
-
X /*
X * If you get a RR, the remote isn't busy anymore,
X * no matter what the NR
@@ -1194,14 +1174,6 @@
X /* Resend rejected frames */
X irlap_resend_rejected_frames( self, CMD_FRAME);
X
- /*
- * Start only if not running, DB
- * TODO: Should this one be here?
- */
- /* if ( !self->final_timer.prev) */
-/* irda_start_timer( FINAL_TIMER, self->final_timeout); */
-
- /* Keep state */
X irlap_next_state( self, LAP_NRM_P);
X } else if (ret == NR_INVALID) {
X DEBUG(1, "irlap_state_nrm_p: received RR with "
@@ -1210,8 +1182,7 @@
X
X irlap_next_state( self, LAP_RESET_WAIT);
X
- irlap_disconnect_indication( self,
- LAP_RESET_INDICATION);
+ irlap_disconnect_indication(self, LAP_RESET_INDICATION);
X self->xmitflag = TRUE;
X }
X if (skb)
@@ -1479,13 +1450,13 @@
X /*
X * Send frame only if send window > 1
X */
- if (( self->window > 0) && ( !self->remote_busy)) {
+ if ((self->window > 0) && ( !self->remote_busy)) {
X /*
X * Test if we have transmitted more bytes over the
X * link than its possible to do with the current
X * speed and turn-around-time.
X */
- if (( skb->len+self->bofs_count) > self->bytes_left) {
+ if ((skb->len+self->bofs_count) > self->bytes_left) {
X DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n");
X skb_queue_head( &self->tx_list, skb);
X /*
@@ -1507,11 +1478,9 @@
X if (( self->window > 1) &&
X skb_queue_len( &self->tx_list) > 0)
X {
- DEBUG( 4, __FUNCTION__ "(), window > 1\n");
X irlap_send_data_secondary( self, skb);
X irlap_next_state( self, LAP_XMIT_S);
X } else {
- DEBUG( 4, "(), window <= 1\n");
X irlap_send_data_secondary_final( self, skb);
X irlap_next_state( self, LAP_NRM_S);
X
@@ -1635,8 +1604,7 @@
X /*
X * Check for Unexpected next to send (Ns)
X */
- if (( ns_status == NS_UNEXPECTED) &&
- ( nr_status == NR_EXPECTED))
+ if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
X {
X /* Unexpected next to send, with final bit cleared */
X if ( !info->pf) {
@@ -1659,8 +1627,7 @@
X /*
X * Unexpected Next to Receive(NR) ?
X */
- if (( ns_status == NS_EXPECTED) &&
- ( nr_status == NR_UNEXPECTED))
+ if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
X {
X if ( info->pf) {
X DEBUG( 4, "RECV_I_RSP: frame(s) lost\n");
@@ -1756,20 +1723,20 @@
X irlap_update_nr_received( self, info->nr);
X del_timer( &self->wd_timer);
X
- irlap_wait_min_turn_around( self, &self->qos_tx);
+ irlap_wait_min_turn_around(self, &self->qos_tx);
X irlap_next_state( self, LAP_XMIT_S);
X } else {
X self->remote_busy = FALSE;
X /* Update Nr received */
- irlap_update_nr_received( self, info->nr);
- irlap_wait_min_turn_around( self, &self->qos_tx);
+ irlap_update_nr_received(self, info->nr);
+ irlap_wait_min_turn_around(self, &self->qos_tx);
X
- irlap_send_rr_frame( self, RSP_FRAME);
+ irlap_send_rr_frame(self, RSP_FRAME);
X
- irlap_start_wd_timer( self, self->wd_timeout);
- irlap_next_state( self, LAP_NRM_S);
+ irlap_start_wd_timer(self, self->wd_timeout);
+ irlap_next_state(self, LAP_NRM_S);
X }
- } else if ( nr_status == NR_UNEXPECTED) {
+ } else if (nr_status == NR_UNEXPECTED) {
X self->remote_busy = FALSE;
X irlap_update_nr_received( self, info->nr);
X irlap_resend_rejected_frames( self, RSP_FRAME);
@@ -1781,8 +1748,8 @@
X } else {
X DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
X }
- if ( skb)
- dev_kfree_skb( skb);
+ if (skb)
+ dev_kfree_skb(skb);
X
X break;
X case RECV_SNRM_CMD:
@@ -1894,7 +1861,7 @@
X ASSERT( self != NULL, return -ENODEV;);
X ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
X
- switch( event) {
+ switch(event) {
X case RESET_RESPONSE:
X irlap_send_ua_response_frame( self, &self->qos_rx);
X irlap_initiate_connection_state( self);
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.5/linux/net/irda/irlap_frame.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlap_frame.c Mon Jun 7 16:18:58 1999


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

X * Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Sun May 9 22:55:11 1999
+ * Modified at: Mon May 31 09:29:13 1999


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

X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>, All Rights Resrved.
@@ -1001,10 +1001,6 @@
X {
X __u8 *frame;
X
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
-
X frame = skb->data;
X
X /* Insert connection address */
@@ -1014,15 +1010,6 @@
X /* Insert next to receive (Vr) */
X frame[1] |= (self->vr << 5); /* insert nr */
X
-#if 0
- {
- int ns;
- ns = (frame[1] >> 1) & 0x07; /* Next to send */
-
- DEBUG(0, __FUNCTION__ "(), ns=%d\n", ns);
- }
-#endif
-
X irlap_queue_xmit(self, skb);
X }
X
@@ -1240,7 +1227,7 @@
X * Optimize for the common case and check if the frame is an
X * I(nformation) frame. Only I-frames have bit 0 set to 0
X */
- if(~control & 0x01) {
+ if (~control & 0x01) {
X irlap_recv_i_frame(self, skb, &info, command);
X self->stats.rx_packets++;
X return 0;
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.3.5/linux/net/irda/irlmp.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlmp.c Mon Jun 7 16:18:58 1999
@@ -6,7 +6,7 @@
X * Status: Stable.


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

X * Created at: Sun Aug 17 20:54:32 1997
- * Modified at: Sun May 9 22:45:06 1999
+ * Modified at: Mon May 31 21:49:41 1999


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

@@ -451,17 +451,16 @@
X ASSERT(skb != NULL, return;);
X ASSERT(self->lap != NULL, return;);
X
- DEBUG(0, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
+ DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
X self->slsap_sel, self->dlsap_sel);
X
X self->qos = *self->lap->qos;
X
- lap_header_size = irlap_get_header_size(self->lap->irlap);
-
- max_seg_size = self->lap->qos->data_size.value-LMP_HEADER-
- lap_header_size;
+ max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
X DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
X
+ lap_header_size = irlap_get_header_size(self->lap->irlap);
+
X max_header_size = LMP_HEADER + lap_header_size;
X
X DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
@@ -519,11 +518,10 @@
X ASSERT(self->lap != NULL, return;);
X self->qos = *self->lap->qos;
X
- lap_header_size = irlap_get_header_size(self->lap->irlap);
-
- max_seg_size = self->lap->qos->data_size.value-LMP_HEADER-
- lap_header_size;
+ max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
X DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+
+ lap_header_size = irlap_get_header_size(self->lap->irlap);
X
X max_header_size = LMP_HEADER + lap_header_size;
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.3.5/linux/net/irda/irlmp_frame.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irlmp_frame.c Mon Jun 7 16:18:58 1999


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

X * Created at: Tue Aug 19 02:09:59 1997
- * Modified at: Sun May 9 21:00:05 1999
+ * Modified at: Mon May 31 09:53:16 1999


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

@@ -134,17 +134,17 @@
X self->lsaps);
X
X if (lsap == NULL) {
- DEBUG(0, "IrLMP, Sorry, no LSAP for received frame!\n");
- DEBUG(0, __FUNCTION__
+ DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
+ DEBUG(2, __FUNCTION__
X "(), slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel,
X dlsap_sel);
X if (fp[0] & CONTROL_BIT) {
- DEBUG(0, __FUNCTION__
+ DEBUG(2, __FUNCTION__
X "(), received control frame %02x\n", fp[2]);
X } else {
- DEBUG(0, __FUNCTION__ "(), received data frame\n");
+ DEBUG(2, __FUNCTION__ "(), received data frame\n");
X }
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
X return;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.5/linux/net/irda/irmod.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irmod.c Mon Jun 7 16:18:58 1999


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

X * Created at: Mon Dec 15 13:55:39 1997
- * Modified at: Mon May 10 15:28:49 1999
+ * Modified at: Fri May 14 13:46:02 1999


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

X * Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -45,7 +45,7 @@
X #include <net/irda/wrapper.h>
X #include <net/irda/timer.h>
X
-extern struct proc_dir_entry proc_irda;
+extern struct proc_dir_entry *proc_irda;
X
X struct irda_cb irda; /* One global instance */
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.3.5/linux/net/irda/irttp.c Mon May 31 22:28:07 1999
+++ linux/net/irda/irttp.c Mon Jun 7 16:18:58 1999


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

X * Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Mon May 10 17:12:53 1999
+ * Modified at: Mon May 31 10:29:56 1999


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

@@ -35,7 +35,7 @@
X #include <net/irda/irlmp.h>
X #include <net/irda/irttp.h>
X
-struct irttp_cb *irttp = NULL;
+static struct irttp_cb *irttp = NULL;
X
X static void __irttp_close_tsap(struct tsap_cb *self);
X
@@ -44,8 +44,7 @@
X static int irttp_udata_indication(void *instance, void *sap,
X struct sk_buff *skb);
X static void irttp_disconnect_indication(void *instance, void *sap,
- LM_REASON reason,
- struct sk_buff *);
+ LM_REASON reason, struct sk_buff *);
X static void irttp_connect_indication(void *instance, void *sap,
X struct qos_info *qos, __u32 max_sdu_size,
X __u8 header_size, struct sk_buff *skb);
@@ -57,8 +56,8 @@
X
X static void irttp_flush_queues(struct tsap_cb *self);
X static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
-static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
X static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
X
X /*
X * Function irttp_init (void)
@@ -298,7 +297,7 @@
X
X /* Check that nothing bad happens */
X if ((skb->len == 0) || (!self->connected)) {
- DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
+ ERROR(__FUNCTION__ "(), No data, or not connected\n");
X return -ENOTCONN;
X }
X
@@ -307,8 +306,8 @@
X * inside an IrLAP frame
X */
X if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
- DEBUG(1, __FUNCTION__
- "(), SAR disabled, and data is to large for IrLAP!\n");
+ ERROR(__FUNCTION__
+ "(), SAR disabled, and data is to large for IrLAP!\n");
X return -EMSGSIZE;
X }
X
@@ -320,8 +319,8 @@
X (self->tx_max_sdu_size != SAR_UNBOUND) &&
X (skb->len > self->tx_max_sdu_size))
X {
- DEBUG(1, __FUNCTION__ "(), SAR enabled, "
- "but data is larger than TxMaxSduSize!\n");
+ ERROR(__FUNCTION__ "(), SAR enabled, "
+ "but data is larger than TxMaxSduSize!\n");
X return -EMSGSIZE;
X }
X /*
@@ -343,7 +342,6 @@
X frame = skb_push(skb, TTP_HEADER);
X frame[0] = 0x00; /* Clear more bit */
X
- DEBUG(4, __FUNCTION__ "(), queueing original skb\n");
X skb_queue_tail(&self->tx_queue, skb);
X } else {
X /*
@@ -384,12 +382,8 @@
X {
X struct sk_buff *skb = NULL;
X unsigned long flags;
- __u8 *frame;
X int n;
X
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
-
X if (irda_lock(&self->tx_queue_lock) == FALSE)
X return;
X
@@ -424,12 +418,7 @@
X * More bit must be set by the data_request() or fragment()
X * functions
X */
- frame = skb->data;
-
- DEBUG(4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ?
- "TRUE" : "FALSE" );
-
- frame[0] |= (__u8) (n & 0x7f);
+ skb->data[0] |= (n & 0x7f);
X
X irlmp_data_request(self->lsap, skb);
X self->stats.tx_packets++;
@@ -437,12 +426,12 @@
X /* Check if we can accept more frames from client */
X if ((self->tx_sdu_busy) &&
X (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD))
- {
+ {
X self->tx_sdu_busy = FALSE;
X
X if (self->notify.flow_indication)
X self->notify.flow_indication(
- self->notify.instance, self,
+ self->notify.instance, self,
X FLOW_START);
X }
X }
@@ -541,23 +530,14 @@
X struct sk_buff *skb)
X {
X struct tsap_cb *self;
- int more;
X int n;
- __u8 *frame;
-
+
X self = (struct tsap_cb *) instance;
X
X ASSERT(self != NULL, return -1;);
X ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
X
- frame = skb->data;
-
- n = frame[0] & 0x7f; /* Extract the credits */
- more = frame[0] & 0x80;
-
- DEBUG(3, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n",
- n, self->stsap_sel);
+ n = skb->data[0] & 0x7f; /* Extract the credits */
X
X self->stats.rx_packets++;
X
@@ -565,10 +545,9 @@
X * Data or dataless frame? Dataless frames only contain the
X * TTP_HEADER
X */
- if (skb->len == 1) {
- /* Dataless flowdata TTP-PDU */
- self->send_credit += n;
- } else {
+ if (skb->len == 1)
+ self->send_credit += n; /* Dataless flowdata TTP-PDU */
+ else {
X /* Deal with inbound credit */
X self->send_credit += n;
X self->remote_credit--;
@@ -768,6 +747,10 @@
X self->connected = TRUE;
X
X parameters = frame[0] & 0x80;
+
+ ASSERT(skb->len >= TTP_HEADER, return;);
+ skb_pull(skb, TTP_HEADER);
+
X if (parameters) {
X plen = frame[1];
X pi = frame[2];
@@ -793,13 +776,15 @@
X
X DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n",
X self->tx_max_sdu_size);
+
+ /* Remove parameters */
+ ASSERT(skb->len >= (plen+1), return;);
+ skb_pull(skb, plen+1);
X }
X
X DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
X self->send_credit, self->avail_credit, self->remote_credit);
X
- skb_pull(skb, TTP_HEADER);
-
X if (self->notify.connect_confirm) {
X self->notify.connect_confirm(self->notify.instance, self, qos,
X self->tx_max_sdu_size,
@@ -814,7 +799,7 @@
X *
X */
X void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
- __u32 max_seg_size, __u8 max_header_size,
+ __u32 max_seg_size, __u8 max_header_size,
X struct sk_buff *skb)
X {
X struct tsap_cb *self;
@@ -847,7 +832,11 @@
X self->send_credit = n;
X self->tx_max_sdu_size = 0;
X
- parameters = frame[0] & 0x80;
+ parameters = frame[0] & 0x80;
+
+ ASSERT(skb->len >= TTP_HEADER, return;);
+ skb_pull(skb, TTP_HEADER);
+
X if (parameters) {
X DEBUG(3, __FUNCTION__ "(), Contains parameters!\n");
X plen = frame[1];
@@ -871,7 +860,10 @@
X "() illegal value length for max_sdu_size!\n");
X self->tx_max_sdu_size = 0;
X };
-
+
+ /* Remove parameters */
+ ASSERT(skb->len >= (plen+1), return;);
+ skb_pull(skb, plen+1);
X
X DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n",
X self->tx_max_sdu_size);
@@ -879,8 +871,6 @@
X
X DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
X
- skb_pull(skb, 1); /* Remove TTP header */
-


X if (self->notify.connect_indication) {
X self->notify.connect_indication(self->notify.instance, self,

X qos, self->rx_max_sdu_size,
@@ -1403,11 +1393,9 @@
X irttp_run_tx_queue(self);
X
X /* Give avay some credits to peer? */
- if ((skb_queue_empty(&self->tx_queue)) &&
- (self->remote_credit < LOW_THRESHOLD) &&
- (self->avail_credit > 0))
+ if ((self->remote_credit < LOW_THRESHOLD) &&
+ (self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
X {


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

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

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part26

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


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

- DEBUG(4, __FUNCTION__ "(), sending credit!\n");
X irttp_give_credit(self);
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.3.5/linux/net/irda/wrapper.c Wed Jun 2 14:44:39 1999
+++ linux/net/irda/wrapper.c Mon Jun 7 16:18:58 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: Sun May 2 21:58:00 1999
+ * Modified at: Fri May 28 20:30:24 1999


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

X * Modified at: Fri May 28 3:11 CST 1999
X * Modified by: Horst von Brand <vonb...@sleipnir.valparaiso.cl>

@@ -219,7 +219,7 @@
X /*
X * Function state_begin_frame (idev, byte)
X *
- *
+ * Begin of frame detected
X *
X */
X static void state_begin_frame(struct irda_device *idev, __u8 byte)
@@ -231,6 +231,10 @@
X case CE:
X /* Stuffed byte */
X idev->rx_buff.state = LINK_ESCAPE;
+
+ /* Time to initialize receive buffer */


+ idev->rx_buff.data = idev->rx_buff.head;

+ idev->rx_buff.len = 0;
X break;
X case EOF:
X /* Abort frame */
@@ -239,11 +243,11 @@
X idev->stats.rx_errors++;
X idev->stats.rx_frame_errors++;
X break;
- default:
- /* Got first byte of frame */
+ default:
+ /* Time to initialize receive buffer */
X idev->rx_buff.data = idev->rx_buff.head;
X idev->rx_buff.len = 0;
-
+
X idev->rx_buff.data[idev->rx_buff.len++] = byte;
X
X idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
@@ -293,7 +297,7 @@
X /*
X * Function state_inside_frame (idev, byte)
X *
- *
+ * Handle bytes received within a frame
X *
X */
X static void state_inside_frame(struct irda_device *idev, __u8 byte)
diff -u --recursive --new-file v2.3.5/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.3.5/linux/net/netrom/nr_route.c Mon May 31 22:28:07 1999
+++ linux/net/netrom/nr_route.c Wed Jun 9 14:45:37 1999
@@ -564,13 +564,13 @@
X {
X struct device *dev, *first = NULL;


X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);

X 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;
X }


- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X return first;
X }
@@ -582,13 +582,13 @@
X {


X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);

X 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)


X goto out;
X }
X out:

- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X return dev;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.5/linux/net/netsyms.c Mon May 31 22:28:07 1999
+++ linux/net/netsyms.c Wed Jun 9 14:45:37 1999
@@ -170,7 +170,6 @@
X
X EXPORT_SYMBOL(neigh_table_init);
X EXPORT_SYMBOL(neigh_table_clear);
-EXPORT_SYMBOL(__neigh_lookup);
X EXPORT_SYMBOL(neigh_resolve_output);
X EXPORT_SYMBOL(neigh_connected_output);
X EXPORT_SYMBOL(neigh_update);
@@ -388,8 +387,7 @@
X EXPORT_SYMBOL(dev_set_allmulti);
X EXPORT_SYMBOL(dev_set_promiscuity);
X EXPORT_SYMBOL(sklist_remove_socket);
-EXPORT_SYMBOL(rtnl_wait);
-EXPORT_SYMBOL(rtnl_rlockct);
+EXPORT_SYMBOL(rtnl_sem);
X EXPORT_SYMBOL(rtnl_lock);
X EXPORT_SYMBOL(rtnl_unlock);
X
diff -u --recursive --new-file v2.3.5/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.3.5/linux/net/packet/af_packet.c Sun Mar 21 07:22:00 1999
+++ linux/net/packet/af_packet.c Wed Jun 9 14:45:37 1999
@@ -5,7 +5,7 @@
X *
X * PACKET - implements raw packet sockets.
X *
- * Version: $Id: af_packet.c,v 1.19 1999/03/21 05:23:03 davem Exp $
+ * Version: $Id: af_packet.c,v 1.20 1999/06/09 10:11:32 davem Exp $
X *


X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>

@@ -286,26 +286,27 @@
X else
X return(-ENOTCONN); /* SOCK_PACKET must be sent giving an address */
X
+ dev_lock_list();
+
X /*
X * Find the device first to size check it
X */
X
X saddr->spkt_device[13] = 0;
X dev = dev_get(saddr->spkt_device);
- if (dev == NULL)
- {
- return(-ENODEV);
- }
+ err = -ENODEV;


+ if (dev == NULL)

+ goto out_unlock;
X
X /*
X * You may not queue a frame bigger than the mtu. This is the lowest level
X * raw protocol and you must do your own fragmentation at this level.
X */
X
- if(len>dev->mtu+dev->hard_header_len)
- return -EMSGSIZE;
+ err = -EMSGSIZE;
+ if(len>dev->mtu+dev->hard_header_len)
+ goto out_unlock;
X
- dev_lock_list();
X err = -ENOBUFS;
X skb = sock_wmalloc(sk, len+dev->hard_header_len+15, 0, GFP_KERNEL);
X
@@ -351,8 +352,8 @@
X * Now send it
X */
X
- dev_unlock_list();
X dev_queue_xmit(skb);
+ dev_unlock_list();
X return(len);
X
X out_free:
@@ -455,16 +456,18 @@
X addr = saddr->sll_addr;
X }
X
+ dev_lock_list();
X dev = dev_get_by_index(ifindex);
+ err = -ENXIO;


X if (dev == NULL)

- return -ENXIO;
+ goto out_unlock;
X if (sock->type == SOCK_RAW)
X reserve = dev->hard_header_len;
X
+ err = -EMSGSIZE;
X if (len > dev->mtu+reserve)
- return -EMSGSIZE;
+ goto out_unlock;
X
- dev_lock_list();
X
X skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0,
X msg->msg_flags & MSG_DONTWAIT, &err);
@@ -501,8 +504,8 @@
X * Now send it
X */
X
- dev_unlock_list();
X dev_queue_xmit(skb);
+ dev_unlock_list();
X return(len);
X
X out_free:
diff -u --recursive --new-file v2.3.5/linux/net/rose/rose_route.c linux/net/rose/rose_route.c
--- v2.3.5/linux/net/rose/rose_route.c Mon May 31 22:28:07 1999
+++ linux/net/rose/rose_route.c Wed Jun 9 14:45:37 1999
@@ -543,13 +543,13 @@
X {
X struct device *dev, *first = NULL;


X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);

X 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;
X }


- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X return first;
X }
@@ -561,13 +561,13 @@
X {


X struct device *dev;
X
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);

X 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)


X goto out;
X }
X out:

- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X return dev;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/sched/cls_api.c linux/net/sched/cls_api.c
--- v2.3.5/linux/net/sched/cls_api.c Thu Mar 25 09:23:34 1999
+++ linux/net/sched/cls_api.c Wed Jun 9 14:45:37 1999
@@ -39,20 +39,24 @@
X
X static struct tcf_proto_ops *tcf_proto_base;
X
+/* Protects list of registered TC modules. It is pure SMP lock. */
+static rwlock_t cls_mod_lock = RW_LOCK_UNLOCKED;
X
X /* Find classifier type by string name */
X
X struct tcf_proto_ops * tcf_proto_lookup_ops(struct rtattr *kind)
X {
- struct tcf_proto_ops *t;
+ struct tcf_proto_ops *t = NULL;
X
X if (kind) {
+ read_lock(&cls_mod_lock);
X for (t = tcf_proto_base; t; t = t->next) {
X if (rtattr_strcmp(kind, t->kind) == 0)
- return t;
+ break;
X }
+ read_unlock(&cls_mod_lock);
X }
- return NULL;
+ return t;
X }
X
X /* Register(unregister) new classifier type */


@@ -61,12 +65,17 @@
X {

X struct tcf_proto_ops *t, **tp;
X
- for (tp = &tcf_proto_base; (t=*tp) != NULL; tp = &t->next)
- if (strcmp(ops->kind, t->kind) == 0)
+ write_lock(&cls_mod_lock);
+ for (tp = &tcf_proto_base; (t=*tp) != NULL; tp = &t->next) {
+ if (strcmp(ops->kind, t->kind) == 0) {
+ write_unlock(&cls_mod_lock);
X return -EEXIST;
+ }
+ }
X
X ops->next = NULL;
X *tp = ops;
+ write_unlock(&cls_mod_lock);


X return 0;
X }
X

@@ -74,13 +83,17 @@
X {
X struct tcf_proto_ops *t, **tp;
X
+ write_lock(&cls_mod_lock);
X for (tp = &tcf_proto_base; (t=*tp) != NULL; tp = &t->next)
X if (t == ops)
X break;
X
- if (!t)
+ if (!t) {
+ write_unlock(&cls_mod_lock);
X return -ENOENT;
+ }
X *tp = t->next;
+ write_unlock(&cls_mod_lock);


X return 0;
X }
X

@@ -217,8 +230,12 @@
X kfree(tp);
X goto errout;
X }
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&dev->queue_lock);
X tp->next = *back;
X *back = tp;
+ spin_unlock_bh(&dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
X } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
X goto errout;
X
@@ -226,8 +243,11 @@
X
X if (fh == 0) {
X if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&dev->queue_lock);
X *back = tp->next;
- synchronize_bh();
+ spin_unlock_bh(&dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
X
X tp->ops->destroy(tp);
X kfree(tp);
@@ -344,12 +364,16 @@
X return skb->len;
X if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
X return skb->len;
+
+ read_lock(&qdisc_tree_lock);
X if (!tcm->tcm_parent)
X q = dev->qdisc_sleeping;
X else
X q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
- if (q == NULL)
+ if (q == NULL) {
+ read_unlock(&qdisc_tree_lock);
X return skb->len;
+ }
X if ((cops = q->ops->cl_ops) == NULL)
X goto errout;
X if (TC_H_MIN(tcm->tcm_parent)) {
@@ -400,6 +424,7 @@
X if (cl)
X cops->put(q, cl);
X
+ read_unlock(&qdisc_tree_lock);
X return skb->len;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/sched/cls_fw.c linux/net/sched/cls_fw.c
--- v2.3.5/linux/net/sched/cls_fw.c Thu Apr 22 19:45:20 1999
+++ linux/net/sched/cls_fw.c Wed Jun 9 14:45:37 1999
@@ -136,7 +136,7 @@
X unsigned long cl;
X head->ht[h] = f->next;
X
- if ((cl = cls_set_class(&f->res.class, 0)) != 0)
+ if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X #ifdef CONFIG_NET_CLS_POLICE
X tcf_police_release(f->police);
@@ -161,10 +161,11 @@
X if (*fp == f) {
X unsigned long cl;
X
+ tcf_tree_lock(tp);
X *fp = f->next;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
- if ((cl = cls_set_class(&f->res.class, 0)) != 0)
+ if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X #ifdef CONFIG_NET_CLS_POLICE
X tcf_police_release(f->police);


@@ -203,7 +204,7 @@
X

X f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
X cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid);
- cl = cls_set_class(&f->res.class, cl);
+ cl = cls_set_class(tp, &f->res.class, cl);
X if (cl)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X }
@@ -211,8 +212,9 @@
X if (tb[TCA_FW_POLICE-1]) {
X struct tcf_police *police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
X
+ tcf_tree_lock(tp);
X police = xchg(&f->police, police);
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
X tcf_police_release(police);
X }
@@ -229,8 +231,9 @@
X return -ENOBUFS;
X memset(head, 0, sizeof(*head));
X
+ tcf_tree_lock(tp);
X tp->root = head;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X }
X
X f = kmalloc(sizeof(struct fw_filter), GFP_KERNEL);
@@ -245,7 +248,7 @@
X if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != 4)
X goto errout;
X f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
- cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
+ cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
X }
X
X #ifdef CONFIG_NET_CLS_POLICE
@@ -254,8 +257,9 @@
X #endif
X
X f->next = head->ht[fw_hash(handle)];
- wmb();
+ tcf_tree_lock(tp);
X head->ht[fw_hash(handle)] = f;
+ tcf_tree_unlock(tp);
X
X *arg = (unsigned long)f;
X return 0;
@@ -335,7 +339,8 @@
X rta->rta_len = skb->tail - b;
X #ifdef CONFIG_NET_CLS_POLICE
X if (f->police) {
- RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats);
+ if (qdisc_copy_stats(skb, &f->police->stats))
+ goto rtattr_failure;
X }
X #endif
X return skb->len;
diff -u --recursive --new-file v2.3.5/linux/net/sched/cls_route.c linux/net/sched/cls_route.c
--- v2.3.5/linux/net/sched/cls_route.c Thu Mar 25 09:23:34 1999
+++ linux/net/sched/cls_route.c Wed Jun 9 14:45:37 1999
@@ -83,11 +83,11 @@
X return id&0xF;
X }
X
-static void route4_reset_fastmap(struct route4_head *head, u32 id)
+static void route4_reset_fastmap(struct device *dev, struct route4_head *head, u32 id)
X {
- start_bh_atomic();
+ spin_lock_bh(&dev->queue_lock);
X memset(head->fastmap, 0, sizeof(head->fastmap));
- end_bh_atomic();
+ spin_unlock_bh(&dev->queue_lock);
X }
X
X static void __inline__
@@ -297,7 +297,7 @@
X unsigned long cl;
X
X b->ht[h2] = f->next;
- if ((cl = cls_set_class(&f->res.class, 0)) != 0)
+ if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X #ifdef CONFIG_NET_CLS_POLICE
X tcf_police_release(f->police);
@@ -329,12 +329,13 @@
X if (*fp == f) {
X unsigned long cl;
X
+ tcf_tree_lock(tp);
X *fp = f->next;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
- route4_reset_fastmap(head, f->id);
+ route4_reset_fastmap(tp->q->dev, head, f->id);
X
- if ((cl = cls_set_class(&f->res.class, 0)) != 0)
+ if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X
X #ifdef CONFIG_NET_CLS_POLICE
@@ -349,8 +350,9 @@
X return 0;
X
X /* OK, session has no flows */
+ tcf_tree_lock(tp);
X head->table[to_hash(h)] = NULL;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
X kfree(b);
X return 0;
@@ -387,7 +389,7 @@
X unsigned long cl;
X
X f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
- cl = cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
+ cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
X if (cl)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X }
@@ -395,8 +397,9 @@
X if (tb[TCA_ROUTE4_POLICE-1]) {
X struct tcf_police *police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
X
+ tcf_tree_lock(tp);
X police = xchg(&f->police, police);
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
X tcf_police_release(police);
X }
@@ -412,8 +415,9 @@
X return -ENOBUFS;
X memset(head, 0, sizeof(struct route4_head));
X
+ tcf_tree_lock(tp);
X tp->root = head;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X }
X
X f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
@@ -475,8 +479,9 @@
X goto errout;
X memset(b, 0, sizeof(*b));
X
+ tcf_tree_lock(tp);
X head->table[h1] = b;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X }
X f->bkt = b;
X
@@ -489,17 +494,18 @@
X goto errout;
X }
X
- cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
+ cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
X #ifdef CONFIG_NET_CLS_POLICE
X if (tb[TCA_ROUTE4_POLICE-1])
X f->police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
X #endif
X
X f->next = f1;
- wmb();
+ tcf_tree_lock(tp);
X *ins_f = f;
+ tcf_tree_unlock(tp);
X
- route4_reset_fastmap(head, f->id);
+ route4_reset_fastmap(tp->q->dev, head, f->id);
X *arg = (unsigned long)f;
X return 0;
X
@@ -589,7 +595,8 @@
X rta->rta_len = skb->tail - b;
X #ifdef CONFIG_NET_CLS_POLICE
X if (f->police) {
- RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats);
+ if (qdisc_copy_stats(skb, &f->police->stats))
+ goto rtattr_failure;
X }
X #endif
X return skb->len;
diff -u --recursive --new-file v2.3.5/linux/net/sched/cls_rsvp.h linux/net/sched/cls_rsvp.h
--- v2.3.5/linux/net/sched/cls_rsvp.h Thu Apr 22 19:45:20 1999
+++ linux/net/sched/cls_rsvp.h Wed Jun 9 14:45:37 1999
@@ -282,7 +282,7 @@
X unsigned long cl;
X
X s->ht[h2] = f->next;
- if ((cl = cls_set_class(&f->res.class, 0)) != 0)
+ if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X #ifdef CONFIG_NET_CLS_POLICE
X tcf_police_release(f->police);
@@ -310,10 +310,11 @@
X unsigned long cl;
X
X
+ tcf_tree_lock(tp);
X *fp = f->next;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
- if ((cl = cls_set_class(&f->res.class, 0)) != 0)
+ if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X
X #ifdef CONFIG_NET_CLS_POLICE
@@ -332,8 +333,9 @@
X for (sp = &((struct rsvp_head*)tp->root)->ht[h&0xFF];
X *sp; sp = &(*sp)->next) {
X if (*sp == s) {
+ tcf_tree_lock(tp);
X *sp = s->next;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
X kfree(s);
X return 0;
@@ -446,7 +448,7 @@
X unsigned long cl;
X
X f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
- cl = cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
+ cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
X if (cl)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X }
@@ -454,8 +456,9 @@
X if (tb[TCA_RSVP_POLICE-1]) {
X struct tcf_police *police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
X
+ tcf_tree_lock(tp);
X police = xchg(&f->police, police);
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
X tcf_police_release(police);
X }
@@ -536,7 +539,7 @@
X
X f->sess = s;
X if (f->tunnelhdr == 0)
- cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
+ cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
X #ifdef CONFIG_NET_CLS_POLICE
X if (tb[TCA_RSVP_POLICE-1])
X f->police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
@@ -659,7 +662,8 @@
X rta->rta_len = skb->tail - b;
X #ifdef CONFIG_NET_CLS_POLICE
X if (f->police) {
- RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats);
+ if (qdisc_copy_stats(skb, &f->police->stats))
+ goto rtattr_failure;
X }
X #endif
X return skb->len;
diff -u --recursive --new-file v2.3.5/linux/net/sched/cls_u32.c linux/net/sched/cls_u32.c
--- v2.3.5/linux/net/sched/cls_u32.c Thu Mar 25 09:23:34 1999
+++ linux/net/sched/cls_u32.c Wed Jun 9 14:45:37 1999


@@ -307,7 +307,7 @@
X {

X unsigned long cl;
X
- if ((cl = cls_set_class(&n->res.class, 0)) != 0)
+ if ((cl = __cls_set_class(&n->res.class, 0)) != 0)
X tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
X #ifdef CONFIG_NET_CLS_POLICE
X tcf_police_release(n->police);
@@ -326,8 +326,9 @@
X if (ht) {
X for (kp = &ht->ht[TC_U32_HASH(key->handle)]; *kp; kp = &(*kp)->next) {
X if (*kp == key) {
+ tcf_tree_lock(tp);
X *kp = key->next;
- synchronize_bh();
+ tcf_tree_unlock(tp);
X
X u32_destroy_key(tp, key);
X return 0;
@@ -346,7 +347,6 @@
X for (h=0; h<=ht->divisor; h++) {
X while ((n = ht->ht[h]) != NULL) {
X ht->ht[h] = n->next;
- synchronize_bh();
X
X u32_destroy_key(tp, n);
X }
@@ -465,8 +465,9 @@
X ht_down->refcnt++;
X }
X
+ sch_tree_lock(q);
X ht_down = xchg(&n->ht_down, ht_down);
- synchronize_bh();
+ sch_tree_unlock(q);
X
X if (ht_down)
X ht_down->refcnt--;
@@ -475,7 +476,9 @@
X unsigned long cl;
X
X n->res.classid = *(u32*)RTA_DATA(tb[TCA_U32_CLASSID-1]);
- cl = cls_set_class(&n->res.class, q->ops->cl_ops->bind_tcf(q, base, n->res.classid));
+ sch_tree_lock(q);
+ cl = __cls_set_class(&n->res.class, q->ops->cl_ops->bind_tcf(q, base, n->res.classid));
+ sch_tree_unlock(q);
X if (cl)
X q->ops->cl_ops->unbind_tcf(q, cl);
X }
@@ -483,8 +486,9 @@
X if (tb[TCA_U32_POLICE-1]) {
X struct tcf_police *police = tcf_police_locate(tb[TCA_U32_POLICE-1], est);
X
+ sch_tree_lock(q);
X police = xchg(&n->police, police);
- synchronize_bh();
+ sch_tree_lock(q);
X
X tcf_police_release(police);
X }
@@ -682,7 +686,8 @@
X rta->rta_len = skb->tail - b;
X #ifdef CONFIG_NET_CLS_POLICE
X if (TC_U32_KEY(n->handle) && n->police) {
- RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &n->police->stats);
+ if (qdisc_copy_stats(skb, &n->police->stats))
+ goto rtattr_failure;
X }
X #endif
X return skb->len;
diff -u --recursive --new-file v2.3.5/linux/net/sched/estimator.c linux/net/sched/estimator.c
--- v2.3.5/linux/net/sched/estimator.c Thu Mar 25 09:23:34 1999
+++ linux/net/sched/estimator.c Wed Jun 9 14:45:37 1999
@@ -97,29 +97,38 @@
X
X static struct qdisc_estimator_head elist[EST_MAX_INTERVAL+1];
X
+/* Estimator array lock */
+static rwlock_t est_lock = RW_LOCK_UNLOCKED;
+
X static void est_timer(unsigned long arg)
X {
X int idx = (int)arg;
X struct qdisc_estimator *e;
X
+ read_lock(&est_lock);
X for (e = elist[idx].list; e; e = e->next) {
- u64 nbytes = e->stats->bytes;
- u32 npackets = e->stats->packets;
+ struct tc_stats *st = e->stats;
+ u64 nbytes;
+ u32 npackets;
X u32 rate;
-
+
+ spin_lock(st->lock);
+ nbytes = st->bytes;
+ npackets = st->packets;
X rate = (nbytes - e->last_bytes)<<(7 - idx);
X e->last_bytes = nbytes;
X e->avbps += ((long)rate - (long)e->avbps) >> e->ewma_log;
- e->stats->bps = (e->avbps+0xF)>>5;
+ st->bps = (e->avbps+0xF)>>5;
X
X rate = (npackets - e->last_packets)<<(12 - idx);
X e->last_packets = npackets;
X e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log;
X e->stats->pps = (e->avpps+0x1FF)>>10;
+ spin_unlock(st->lock);
X }
X
- elist[idx].timer.expires = jiffies + ((HZ/4)<<idx);
- add_timer(&elist[idx].timer);
+ mod_timer(&elist[idx].timer, jiffies + ((HZ/4)<<idx));
+ read_unlock(&est_lock);
X }
X
X int qdisc_new_estimator(struct tc_stats *stats, struct rtattr *opt)
@@ -154,7 +163,9 @@
X elist[est->interval].timer.function = est_timer;
X add_timer(&elist[est->interval].timer);
X }
+ write_lock_bh(&est_lock);
X elist[est->interval].list = est;
+ write_unlock_bh(&est_lock);


X return 0;
X }
X

@@ -172,8 +183,9 @@
X continue;
X }
X
+ write_lock_bh(&est_lock);
X *pest = est->next;
- synchronize_bh();
+ write_unlock_bh(&est_lock);
X
X kfree(est);
X killed++;
diff -u --recursive --new-file v2.3.5/linux/net/sched/police.c linux/net/sched/police.c
--- v2.3.5/linux/net/sched/police.c Sun Mar 21 07:22:00 1999
+++ linux/net/sched/police.c Wed Jun 9 14:45:37 1999
@@ -38,6 +38,10 @@
X
X static u32 idx_gen;
X static struct tcf_police *tcf_police_ht[16];
+/* Policer hash table lock */
+static rwlock_t police_lock = RW_LOCK_UNLOCKED;
+
+/* Each policer is serialized by its individual spinlock */
X
X static __inline__ unsigned tcf_police_hash(u32 index)
X {
@@ -48,11 +52,13 @@
X {
X struct tcf_police *p;
X
+ read_lock(&police_lock);
X for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) {
X if (p->index == index)
- return p;
+ break;
X }
- return NULL;
+ read_unlock(&police_lock);
+ return p;
X }
X
X static __inline__ u32 tcf_police_new_index(void)
@@ -73,7 +79,9 @@
X
X for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
X if (*p1p == p) {
+ write_lock_bh(&police_lock);
X *p1p = p->next;
+ write_unlock_bh(&police_lock);
X #ifdef CONFIG_NET_ESTIMATOR
X qdisc_kill_estimator(&p->stats);
X #endif
@@ -114,6 +122,8 @@
X
X memset(p, 0, sizeof(*p));
X p->refcnt = 1;
+ spin_lock_init(&p->lock);
+ p->stats.lock = &p->lock;
X if (parm->rate.rate) {
X if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL)
X goto failure;
@@ -144,8 +154,10 @@
X qdisc_new_estimator(&p->stats, est);
X #endif
X h = tcf_police_hash(p->index);
+ write_lock_bh(&police_lock);
X p->next = tcf_police_ht[h];
X tcf_police_ht[h] = p;
+ write_unlock_bh(&police_lock);
X return p;
X
X failure:
@@ -161,19 +173,24 @@
X long toks;
X long ptoks = 0;
X
+ spin_lock(&p->lock);
+
X p->stats.bytes += skb->len;
X p->stats.packets++;
X
X #ifdef CONFIG_NET_ESTIMATOR
X if (p->ewma_rate && p->stats.bps >= p->ewma_rate) {
X p->stats.overlimits++;
+ spin_unlock(&p->lock);
X return p->action;
X }
X #endif
X
X if (skb->len <= p->mtu) {
- if (p->R_tab == NULL)
+ if (p->R_tab == NULL) {
+ spin_unlock(&p->lock);
X return p->result;
+ }
X
X PSCHED_GET_TIME(now);
X
@@ -194,11 +211,13 @@
X p->t_c = now;
X p->toks = toks;
X p->ptoks = ptoks;
+ spin_unlock(&p->lock);
X return p->result;
X }
X }
X
X p->stats.overlimits++;
+ spin_unlock(&p->lock);
X return p->action;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.3.5/linux/net/sched/sch_api.c Mon May 31 22:28:07 1999
+++ linux/net/sched/sch_api.c Wed Jun 9 14:45:37 1999
@@ -124,6 +124,10 @@
X changes qdisc parameters.
X */
X
+/* Protects list of registered TC modules. It is pure SMP lock. */
+static rwlock_t qdisc_mod_lock = RW_LOCK_UNLOCKED;
+
+
X /************************************************
X * Queueing disciplines manipulation. *
X ************************************************/
@@ -139,9 +143,13 @@
X {
X struct Qdisc_ops *q, **qp;
X
- for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
- if (strcmp(qops->id, q->id) == 0)
+ write_lock(&qdisc_mod_lock);
+ for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next) {
+ if (strcmp(qops->id, q->id) == 0) {
+ write_unlock(&qdisc_mod_lock);
X return -EEXIST;
+ }
+ }
X
X if (qops->enqueue == NULL)
X qops->enqueue = noop_qdisc_ops.enqueue;
@@ -152,20 +160,26 @@
X
X qops->next = NULL;
X *qp = qops;
+ write_unlock(&qdisc_mod_lock);


X return 0;
X }
X

X int unregister_qdisc(struct Qdisc_ops *qops)
X {
X struct Qdisc_ops *q, **qp;
+ int err = -ENOENT;
+
+ write_lock(&qdisc_mod_lock);
X for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
X if (q == qops)
X break;
- if (!q)
- return -ENOENT;
- *qp = q->next;
- q->next = NULL;
- return 0;
+ if (q) {
+ *qp = q->next;
+ q->next = NULL;


+ err = 0;
+ }

+ write_unlock(&qdisc_mod_lock);


+ return err;
X }
X

X /* We know handle. Find qdisc among all qdisc's attached to device


@@ -203,15 +217,17 @@
X

X struct Qdisc_ops *qdisc_lookup_ops(struct rtattr *kind)
X {
- struct Qdisc_ops *q;
+ struct Qdisc_ops *q = NULL;
X
X if (kind) {
+ read_lock(&qdisc_mod_lock);
X for (q = qdisc_base; q; q = q->next) {
X if (rtattr_strcmp(kind, q->id) == 0)
- return q;
+ break;
X }
+ read_unlock(&qdisc_mod_lock);
X }
- return NULL;
+ return q;
X }
X
X static struct qdisc_rate_table *qdisc_rtab_list;
@@ -284,7 +300,8 @@
X if (dev->flags & IFF_UP)
X dev_deactivate(dev);
X
- start_bh_atomic();
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&dev->queue_lock);
X oqdisc = dev->qdisc_sleeping;
X
X /* Prune old scheduler */
@@ -296,7 +313,8 @@
X qdisc = &noop_qdisc;
X dev->qdisc_sleeping = qdisc;
X dev->qdisc = &noop_qdisc;
- end_bh_atomic();
+ spin_unlock_bh(&dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
X
X if (dev->flags & IFF_UP)
X dev_activate(dev);
@@ -376,7 +394,7 @@
X goto err_out;
X
X /* Grrr... Resolve race condition with module unload */
-
+
X err = -EINVAL;
X if (ops != qdisc_lookup_ops(kind))
X goto err_out;
@@ -389,6 +407,7 @@
X sch->dequeue = ops->dequeue;
X sch->dev = dev;
X atomic_set(&sch->refcnt, 1);
+ sch->stats.lock = &dev->queue_lock;
X if (handle == 0) {
X handle = qdisc_alloc_handle(dev);
X err = -ENOMEM;
@@ -398,8 +417,10 @@
X sch->handle = handle;
X
X if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
+ write_lock(&qdisc_tree_lock);
X sch->next = dev->qdisc_list;
X dev->qdisc_list = sch;
+ write_unlock(&qdisc_tree_lock);
X #ifdef CONFIG_NET_ESTIMATOR
X if (tca[TCA_RATE-1])
X qdisc_new_estimator(&sch->stats, tca[TCA_RATE-1]);
@@ -521,7 +542,9 @@
X return err;
X if (q) {
X qdisc_notify(skb, n, clid, q, NULL);
+ spin_lock_bh(&dev->queue_lock);
X qdisc_destroy(q);
+ spin_unlock_bh(&dev->queue_lock);
X }
X } else {
X qdisc_notify(skb, n, clid, NULL, q);
@@ -637,17 +660,36 @@
X struct Qdisc *old_q = NULL;
X err = qdisc_graft(dev, p, clid, q, &old_q);
X if (err) {
- if (q)
+ if (q) {
+ spin_lock_bh(&dev->queue_lock);
X qdisc_destroy(q);
+ spin_unlock_bh(&dev->queue_lock);
+ }
X return err;
X }
X qdisc_notify(skb, n, clid, old_q, q);
- if (old_q)
+ if (old_q) {
+ spin_lock_bh(&dev->queue_lock);
X qdisc_destroy(old_q);
+ spin_unlock_bh(&dev->queue_lock);
+ }


X }
X return 0;
X }

X
+int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st)
+{
+ spin_lock_bh(st->lock);
+ RTA_PUT(skb, TCA_STATS, (char*)&st->lock - (char*)st, st);
+ spin_unlock_bh(st->lock);
+ return 0;
+
+rtattr_failure:
+ spin_unlock_bh(st->lock);


+ return -1;
+}
+
+

X static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
X u32 pid, u32 seq, unsigned flags, int event)
X {
@@ -667,7 +709,8 @@
X if (q->ops->dump && q->ops->dump(q, skb) < 0)
X goto rtattr_failure;
X q->stats.qlen = q->q.qlen;
- RTA_PUT(skb, TCA_STATS, sizeof(q->stats), &q->stats);
+ if (qdisc_copy_stats(skb, &q->stats))
+ goto rtattr_failure;


X nlh->nlmsg_len = skb->tail - b;
X return skb->len;

X
@@ -713,24 +756,28 @@


X
X s_idx = cb->args[0];

X s_q_idx = q_idx = cb->args[1];
- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);


X for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
X if (idx < s_idx)
X continue;

X if (idx > s_idx)
X s_q_idx = 0;
+ read_lock(&qdisc_tree_lock);
X for (q = dev->qdisc_list, q_idx = 0; q;
X q = q->next, q_idx++) {
X if (q_idx < s_q_idx)
X continue;
X if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0)
+ cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
+ read_unlock(&qdisc_tree_lock);


X goto done;
+ }
X }

+ read_unlock(&qdisc_tree_lock);
X }
X
X done:


- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X cb->args[0] = idx;

X cb->args[1] = q_idx;
@@ -936,6 +983,7 @@


X
X s_t = cb->args[0];
X

+ read_lock(&qdisc_tree_lock);
X for (q=dev->qdisc_list, t=0; q; q = q->next, t++) {


X if (t < s_t) continue;

X if (!q->ops->cl_ops) continue;
@@ -954,6 +1002,7 @@
X if (arg.w.stop)
X break;
X }
+ read_unlock(&qdisc_tree_lock);


X
X cb->args[0] = t;

X
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c
--- v2.3.5/linux/net/sched/sch_cbq.c Sat Apr 24 17:51:48 1999
+++ linux/net/sched/sch_cbq.c Wed Jun 9 14:45:37 1999
@@ -1417,6 +1417,7 @@
X q->link.ewma_log = TC_CBQ_DEF_EWMA;
X q->link.avpkt = q->link.allot/2;
X q->link.minidle = -0x7FFFFFFF;
+ q->link.stats.lock = &sch->dev->queue_lock;
X
X init_timer(&q->wd_timer);
X q->wd_timer.data = (unsigned long)sch;
@@ -1558,6 +1559,16 @@


X return 0;
X }
X

+int cbq_copy_xstats(struct sk_buff *skb, struct tc_cbq_xstats *st)
+{
+ RTA_PUT(skb, TCA_STATS, sizeof(*st), st);
+ return 0;
+
+rtattr_failure:


+ return -1;
+}
+
+

X static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
X {
X struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data;
@@ -1569,8 +1580,13 @@
X if (cbq_dump_attr(skb, &q->link) < 0)
X goto rtattr_failure;
X rta->rta_len = skb->tail - b;
+ spin_lock_bh(&sch->dev->queue_lock);
X q->link.xstats.avgidle = q->link.avgidle;
- RTA_PUT(skb, TCA_XSTATS, sizeof(q->link.xstats), &q->link.xstats);
+ if (cbq_copy_xstats(skb, &q->link.xstats)) {
+ spin_unlock_bh(&sch->dev->queue_lock);
+ goto rtattr_failure;
+ }
+ spin_unlock_bh(&sch->dev->queue_lock);


X return skb->len;
X

X rtattr_failure:
@@ -1600,12 +1616,19 @@
X goto rtattr_failure;
X rta->rta_len = skb->tail - b;
X cl->stats.qlen = cl->q->q.qlen;
- RTA_PUT(skb, TCA_STATS, sizeof(cl->stats), &cl->stats);
+ if (qdisc_copy_stats(skb, &cl->stats))
+ goto rtattr_failure;
+ spin_lock_bh(&sch->dev->queue_lock);
X cl->xstats.avgidle = cl->avgidle;
X cl->xstats.undertime = 0;
X if (!PSCHED_IS_PASTPERFECT(cl->undertime))
X cl->xstats.undertime = PSCHED_TDIFF(cl->undertime, q->now);
- RTA_PUT(skb, TCA_XSTATS, sizeof(cl->xstats), &cl->xstats);
+ q->link.xstats.avgidle = q->link.avgidle;
+ if (cbq_copy_xstats(skb, &cl->xstats)) {
+ spin_unlock_bh(&sch->dev->queue_lock);
+ goto rtattr_failure;
+ }
+ spin_unlock_bh(&sch->dev->queue_lock);


X
X return skb->len;

X
@@ -1631,8 +1654,11 @@
X new->reshape_fail = cbq_reshape_fail;
X #endif
X }
- if ((*old = xchg(&cl->q, new)) != NULL)
- qdisc_reset(*old);
+ sch_tree_lock(sch);
+ *old = cl->q;
+ cl->q = new;
+ qdisc_reset(*old);
+ sch_tree_unlock(sch);


X
X return 0;
X }

@@ -1710,16 +1736,16 @@
X struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
X struct cbq_class *cl = (struct cbq_class*)arg;
X
- start_bh_atomic();
X if (--cl->refcnt == 0) {
X #ifdef CONFIG_NET_CLS_POLICE
+ spin_lock_bh(&sch->dev->queue_lock);
X if (q->rx_class == cl)
X q->rx_class = NULL;
+ spin_unlock_bh(&sch->dev->queue_lock);
X #endif
+
X cbq_destroy_class(cl);
X }
- end_bh_atomic();
- return;


X }
X
X static int

@@ -1780,7 +1806,7 @@
X }
X
X /* Change class parameters */
- start_bh_atomic();
+ sch_tree_lock(sch);
X
X if (cl->next_alive != NULL)
X cbq_deactivate_class(cl);
@@ -1812,7 +1838,7 @@
X if (cl->q->q.qlen)
X cbq_activate_class(cl);
X
- end_bh_atomic();
+ sch_tree_lock(sch);
X
X #ifdef CONFIG_NET_ESTIMATOR
X if (tca[TCA_RATE-1]) {
@@ -1878,8 +1904,9 @@
X cl->allot = parent->allot;
X cl->quantum = cl->allot;
X cl->weight = cl->R_tab->rate.rate;
+ cl->stats.lock = &sch->dev->queue_lock;
X
- start_bh_atomic();
+ sch_tree_lock(sch);
X cbq_link_class(cl);
X cl->borrow = cl->tparent;
X if (cl->tparent != &q->link)
@@ -1903,7 +1930,7 @@
X #endif
X if (tb[TCA_CBQ_FOPT-1])
X cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
- end_bh_atomic();
+ sch_tree_unlock(sch);
X
X #ifdef CONFIG_NET_ESTIMATOR
X if (tca[TCA_RATE-1])
@@ -1926,7 +1953,7 @@
X if (cl->filters || cl->children || cl == &q->link)
X return -EBUSY;
X
- start_bh_atomic();
+ sch_tree_lock(sch);
X
X if (cl->next_alive)
X cbq_deactivate_class(cl);
@@ -1948,11 +1975,10 @@
X cbq_sync_defmap(cl);
X
X cbq_rmprio(q, cl);
+ sch_tree_unlock(sch);
X
X if (--cl->refcnt == 0)
X cbq_destroy_class(cl);
-
- end_bh_atomic();
X
X return 0;
X }
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_csz.c linux/net/sched/sch_csz.c
--- v2.3.5/linux/net/sched/sch_csz.c Sun Mar 21 07:22:00 1999
+++ linux/net/sched/sch_csz.c Wed Jun 9 14:45:37 1999
@@ -885,7 +885,7 @@
X
X a = &q->flow[cl];
X
- start_bh_atomic();
+ spin_lock_bh(&sch->dev->queue_lock);
X #if 0
X a->rate_log = copt->rate_log;
X #endif
@@ -899,7 +899,7 @@
X if (tb[TCA_CSZ_RTAB-1])
X memcpy(a->L_tab, RTA_DATA(tb[TCA_CSZ_RTAB-1]), 1024);
X
- end_bh_atomic();
+ spin_unlock_bh(&sch->dev->queue_lock);
X return 0;
X }
X /* NI */


@@ -920,14 +920,14 @@
X

X a = &q->flow[cl];
X
- start_bh_atomic();
+ spin_lock_bh(&sch->dev->queue_lock);
X a->fprev->fnext = a->fnext;
X a->fnext->fprev = a->fprev;
X a->sprev->snext = a->snext;
X a->snext->sprev = a->sprev;
X a->start = a->finish = 0;
X kfree(xchg(&q->flow[cl].L_tab, NULL));
- end_bh_atomic();
+ spin_unlock_bh(&sch->dev->queue_lock);
X
X return 0;
X }
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
--- v2.3.5/linux/net/sched/sch_generic.c Mon May 31 22:28:07 1999
+++ linux/net/sched/sch_generic.c Wed Jun 9 14:45:37 1999
@@ -34,7 +34,45 @@
X
X /* Main transmission queue. */
X
-struct Qdisc_head qdisc_head = { &qdisc_head };
+struct Qdisc_head qdisc_head = { &qdisc_head, &qdisc_head };
+spinlock_t qdisc_runqueue_lock = SPIN_LOCK_UNLOCKED;
+
+/* Main qdisc structure lock.
+
+ However, modifications
+ to data, participating in scheduling must be additionally
+ protected with dev->queue_lock spinlock.
+
+ The idea is the following:
+ - enqueue, dequeue are serialized via top level device
+ spinlock dev->queue_lock.
+ - tree walking is protected by read_lock(qdisc_tree_lock)
+ and this lock is used only in process context.
+ - updates to tree are made only under rtnl semaphore,
+ hence this lock may be made without local bh disabling.
+
+ qdisc_tree_lock must be grabbed BEFORE dev->queue_lock!
+ */
+rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED;
+
+/* Anti deadlock rules:
+
+ qdisc_runqueue_lock protects main transmission list qdisc_head.
+ Run list is accessed only under this spinlock.
+
+ dev->queue_lock serializes queue accesses for this device
+ AND dev->qdisc pointer itself.
+
+ dev->xmit_lock serializes accesses to device driver.
+
+ dev->queue_lock and dev->xmit_lock are mutually exclusive,
+ if one is grabbed, another must be free.
+
+ qdisc_runqueue_lock may be requested under dev->queue_lock,
+ but neither dev->queue_lock nor dev->xmit_lock may be requested
+ under qdisc_runqueue_lock.
+ */
+
X
X /* Kick device.
X Note, that this procedure can be called by a watchdog timer, so that
@@ -44,7 +82,7 @@
X >0 - queue is not empty, but throttled.
X <0 - queue is not empty. Device is throttled, if dev->tbusy != 0.
X
- NOTE: Called only from NET BH
+ NOTE: Called under dev->queue_lock with locally disabled BH.
X */
X
X int qdisc_restart(struct device *dev)
@@ -53,27 +91,97 @@


X struct sk_buff *skb;
X

X if ((skb = q->dequeue(q)) != NULL) {
+ /* Dequeue packet and release queue */
+ spin_unlock(&dev->queue_lock);
+
X if (netdev_nit)
X dev_queue_xmit_nit(skb, dev);
X

- if (dev->hard_start_xmit(skb, dev) == 0) {

- q->tx_last = jiffies;
- return -1;
+ if (spin_trylock(&dev->xmit_lock)) {
+ /* Remember that the driver is grabbed by us. */


+ dev->xmit_lock_owner = smp_processor_id();
+ if (dev->hard_start_xmit(skb, dev) == 0) {
+ dev->xmit_lock_owner = -1;

+ spin_unlock(&dev->xmit_lock);
+
+ spin_lock(&dev->queue_lock);
+ dev->qdisc->tx_last = jiffies;
+ return -1;
+ }
+ /* Release the driver */


+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);

+ } else {
+ /* So, someone grabbed the driver. */
+
+ /* It may be transient configuration error,
+ when hard_start_xmit() recurses. We detect
+ it by checking xmit owner and drop the
+ packet when deadloop is detected.
+ */
+ if (dev->xmit_lock_owner == smp_processor_id()) {
+ kfree_skb(skb);
+ if (net_ratelimit())
+ printk(KERN_DEBUG "Dead loop on virtual %s, fix it urgently!\n", dev->name);
+ spin_lock(&dev->queue_lock);


+ return -1;
+ }
+

+ /* Otherwise, packet is requeued
+ and will be sent by the next net_bh run.
+ */
+ mark_bh(NET_BH);
X }
X
X /* Device kicked us out :(
X This is possible in three cases:
X
+ 0. driver is locked
X 1. fastroute is enabled
X 2. device cannot determine busy state
X before start of transmission (f.e. dialout)
X 3. device is buggy (ppp)
X */
X
+ spin_lock(&dev->queue_lock);
+ q = dev->qdisc;
X q->ops->requeue(skb, q);
X return -1;
X }
- return q->q.qlen;
+ return dev->qdisc->q.qlen;
+}
+
+static __inline__ void
+qdisc_stop_run(struct Qdisc *q)
+{
+ q->h.forw->back = q->h.back;
+ q->h.back->forw = q->h.forw;
+ q->h.forw = NULL;


+}
+
+extern __inline__ void

+qdisc_continue_run(struct Qdisc *q)
+{
+ if (!qdisc_on_runqueue(q) && q->dev) {


+ q->h.forw = &qdisc_head;
+ q->h.back = qdisc_head.back;
+ qdisc_head.back->forw = &q->h;
+ qdisc_head.back = &q->h;
+ }
+}

+
+static __inline__ int
+qdisc_init_run(struct Qdisc_head *lh)
+{
+ if (qdisc_head.forw != &qdisc_head) {
+ *lh = qdisc_head;
+ lh->forw->back = lh;
+ lh->back->forw = lh;
+ qdisc_head.forw = &qdisc_head;
+ qdisc_head.back = &qdisc_head;
+ return 1;
+ }


+ return 0;
X }
X

X /* Scan transmission queue and kick devices.
@@ -84,63 +192,90 @@
X I have no idea how to solve it using only "anonymous" Linux mark_bh().
X
X To change queue from device interrupt? Ough... only not this...
+
+ This function is called only from net_bh.
X */
X
X void qdisc_run_queues(void)
X {
- struct Qdisc_head **hp, *h;
+ struct Qdisc_head lh, *h;
X
- hp = &qdisc_head.forw;
- while ((h = *hp) != &qdisc_head) {
- int res = -1;
+ spin_lock(&qdisc_runqueue_lock);
+ if (!qdisc_init_run(&lh))
+ goto out;
+
+ while ((h = lh.forw) != &lh) {
+ int res;
+ struct device *dev;
X struct Qdisc *q = (struct Qdisc*)h;
- struct device *dev = q->dev;
X
- spin_lock_bh(&dev->xmit_lock);
- while (!dev->tbusy && (res = qdisc_restart(dev)) < 0)
- /* NOTHING */;
- spin_unlock_bh(&dev->xmit_lock);
-
- /* An explanation is necessary here.
- qdisc_restart called dev->hard_start_xmit,
- if device is virtual, it could trigger one more
- dev_queue_xmit and a new device could appear
- in the active chain. In this case we cannot unlink
- the empty queue, because we lost the back pointer.
- No problem, we will unlink it during the next round.
- */
+ qdisc_stop_run(q);
+
+ dev = q->dev;
+ spin_unlock(&qdisc_runqueue_lock);
X
- if (res == 0 && *hp == h) {
- *hp = h->forw;
- h->forw = NULL;
- continue;
+ res = -1;
+ if (spin_trylock(&dev->queue_lock)) {
+ while (!dev->tbusy && (res = qdisc_restart(dev)) < 0)
+ /* NOTHING */;
+ spin_unlock(&dev->queue_lock);
X }
- hp = &h->forw;
+
+ spin_lock(&qdisc_runqueue_lock);
+ /* If qdisc is not empty add it to the tail of list */
+ if (res)
+ qdisc_continue_run(q);
X }
+out:
+ spin_unlock(&qdisc_runqueue_lock);
X }
X
-/* Periodic watchdoc timer to recover from hard/soft device bugs. */
+/* Periodic watchdog timer to recover from hard/soft device bugs. */
X
X static void dev_do_watchdog(unsigned long dummy);
X
X static struct timer_list dev_watchdog =
X { NULL, NULL, 0L, 0L, &dev_do_watchdog };
X
+/* This function is called only from timer */
+
X static void dev_do_watchdog(unsigned long dummy)
X {
- struct Qdisc_head *h;
+ struct Qdisc_head lh, *h;
+
+ if (!spin_trylock(&qdisc_runqueue_lock)) {
+ /* No hurry with watchdog. */
+ mod_timer(&dev_watchdog, jiffies + HZ/10);
+ return;
+ }
+
+ if (!qdisc_init_run(&lh))
+ goto out;
X
- for (h = qdisc_head.forw; h != &qdisc_head; h = h->forw) {
+ while ((h = lh.forw) != &lh) {
+ struct device *dev;
X struct Qdisc *q = (struct Qdisc*)h;
- struct device *dev = q->dev;
X
- spin_lock_bh(&dev->xmit_lock);
- if (dev->tbusy && jiffies - q->tx_last > q->tx_timeo)
- qdisc_restart(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ qdisc_stop_run(q);
+
+ dev = q->dev;
+ spin_unlock(&qdisc_runqueue_lock);
+
+ if (spin_trylock(&dev->queue_lock)) {
+ q = dev->qdisc;
+ if (dev->tbusy && jiffies - q->tx_last > q->tx_timeo)
+ qdisc_restart(dev);
+ spin_unlock(&dev->queue_lock);
+ }
+
+ spin_lock(&qdisc_runqueue_lock);
+
+ qdisc_continue_run(dev->qdisc);
X }
- dev_watchdog.expires = jiffies + 5*HZ;
- add_timer(&dev_watchdog);
+
+out:
+ mod_timer(&dev_watchdog, jiffies + 5*HZ);
+ spin_unlock(&qdisc_runqueue_lock);
X }
X
X
@@ -211,7 +346,7 @@
X {
X { NULL },
X NULL,
- NULL,
+ noop_dequeue,
X TCQ_F_BUILTIN,
X &noqueue_qdisc_ops,
X };
@@ -327,6 +462,7 @@
X sch->enqueue = ops->enqueue;
X sch->dequeue = ops->dequeue;
X sch->dev = dev;
+ sch->stats.lock = &dev->queue_lock;
X atomic_set(&sch->refcnt, 1);
X if (!ops->init || ops->init(sch, NULL) == 0)
X return sch;
@@ -335,42 +471,45 @@
X return NULL;
X }
X
+/* Under dev->queue_lock and BH! */
+
X void qdisc_reset(struct Qdisc *qdisc)
X {
X struct Qdisc_ops *ops = qdisc->ops;
- start_bh_atomic();
X if (ops->reset)
X ops->reset(qdisc);
- end_bh_atomic();
X }
X
+/* Under dev->queue_lock and BH! */
+
X void qdisc_destroy(struct Qdisc *qdisc)
X {
X struct Qdisc_ops *ops = qdisc->ops;
+ struct device *dev;
X
X if (!atomic_dec_and_test(&qdisc->refcnt))
X return;
X
+ dev = qdisc->dev;
+
X #ifdef CONFIG_NET_SCHED
- if (qdisc->dev) {
+ if (dev) {
X struct Qdisc *q, **qp;
- for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next)
+ for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
X if (q == qdisc) {
X *qp = q->next;
- q->next = NULL;
X break;
X }
+ }
X }
X #ifdef CONFIG_NET_ESTIMATOR
X qdisc_kill_estimator(&qdisc->stats);
X #endif
X #endif
- start_bh_atomic();
X if (ops->reset)
X ops->reset(qdisc);
X if (ops->destroy)
X ops->destroy(qdisc);
- end_bh_atomic();
X if (!(qdisc->flags&TCQ_F_BUILTIN))
X kfree(qdisc);
X }
@@ -385,19 +524,23 @@
X */
X
X if (dev->qdisc_sleeping == &noop_qdisc) {
+ struct Qdisc *qdisc;
X if (dev->tx_queue_len) {
- struct Qdisc *qdisc;
X qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops);
X if (qdisc == NULL) {
X printk(KERN_INFO "%s: activation failed\n", dev->name);
X return;
X }
- dev->qdisc_sleeping = qdisc;
- } else
- dev->qdisc_sleeping = &noqueue_qdisc;
+ } else {
+ qdisc = &noqueue_qdisc;
+ }
+ write_lock(&qdisc_tree_lock);
+ dev->qdisc_sleeping = qdisc;
+ write_unlock(&qdisc_tree_lock);
X }
X
- start_bh_atomic();
+ spin_lock_bh(&dev->queue_lock);
+ spin_lock(&qdisc_runqueue_lock);
X if ((dev->qdisc = dev->qdisc_sleeping) != &noqueue_qdisc) {
X dev->qdisc->tx_timeo = 5*HZ;
X dev->qdisc->tx_last = jiffies - dev->qdisc->tx_timeo;
@@ -405,51 +548,50 @@
X dev_watchdog.expires = jiffies + 5*HZ;
X add_timer(&dev_watchdog);
X }
- end_bh_atomic();
+ spin_unlock(&qdisc_runqueue_lock);


+ spin_unlock_bh(&dev->queue_lock);
X }
X

X void dev_deactivate(struct device *dev)
X {
X struct Qdisc *qdisc;
X
- start_bh_atomic();
-
- qdisc = xchg(&dev->qdisc, &noop_qdisc);
+ spin_lock_bh(&dev->queue_lock);
+ qdisc = dev->qdisc;
+ dev->qdisc = &noop_qdisc;
X
X qdisc_reset(qdisc);
X
- if (qdisc->h.forw) {
- struct Qdisc_head **hp, *h;
-
- for (hp = &qdisc_head.forw; (h = *hp) != &qdisc_head; hp = &h->forw) {
- if (h == &qdisc->h) {
- *hp = h->forw;


- break;
- }
- }
- }

-
- end_bh_atomic();
+ spin_lock(&qdisc_runqueue_lock);
+ if (qdisc_on_runqueue(qdisc))
+ qdisc_stop_run(qdisc);
+ spin_unlock(&qdisc_runqueue_lock);


+ spin_unlock_bh(&dev->queue_lock);
X }
X

X void dev_init_scheduler(struct device *dev)
X {
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&dev->queue_lock);
X dev->qdisc = &noop_qdisc;
+ spin_unlock_bh(&dev->queue_lock);
X dev->qdisc_sleeping = &noop_qdisc;
X dev->qdisc_list = NULL;
+ write_unlock(&qdisc_tree_lock);
X }
X
X void dev_shutdown(struct device *dev)
X {
X struct Qdisc *qdisc;
X
- start_bh_atomic();
+ write_lock(&qdisc_tree_lock);
+ spin_lock_bh(&dev->queue_lock);
X qdisc = dev->qdisc_sleeping;
X dev->qdisc = &noop_qdisc;
X dev->qdisc_sleeping = &noop_qdisc;
X qdisc_destroy(qdisc);
X BUG_TRAP(dev->qdisc_list == NULL);
X dev->qdisc_list = NULL;
- end_bh_atomic();
+ spin_unlock_bh(&dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
X }
-
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_prio.c linux/net/sched/sch_prio.c
--- v2.3.5/linux/net/sched/sch_prio.c Thu Mar 25 09:23:34 1999
+++ linux/net/sched/sch_prio.c Wed Jun 9 14:45:37 1999
@@ -178,7 +178,7 @@


X return -EINVAL;
X }
X

- start_bh_atomic();
+ sch_tree_lock(sch);
X q->bands = qopt->bands;
X memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
X
@@ -187,7 +187,7 @@
X if (child != &noop_qdisc)
X qdisc_destroy(child);
X }
- end_bh_atomic();
+ sch_tree_unlock(sch);
X
X for (i=0; i<=TC_PRIO_MAX; i++) {
X int band = q->prio2band[i];
@@ -195,11 +195,12 @@
X struct Qdisc *child;
X child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
X if (child) {
+ sch_tree_lock(sch);
X child = xchg(&q->queues[band], child);
- synchronize_bh();
X
X if (child != &noop_qdisc)
X qdisc_destroy(child);
+ sch_tree_unlock(sch);
X }
X }
X }
@@ -265,7 +266,11 @@
X if (new == NULL)
X new = &noop_qdisc;
X
- *old = xchg(&q->queues[band], new);
+ sch_tree_lock(sch);
+ *old = q->queues[band];
+ q->queues[band] = new;
+ qdisc_reset(*old);
+ sch_tree_unlock(sch);
X
X return 0;
X }
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_sfq.c linux/net/sched/sch_sfq.c
--- v2.3.5/linux/net/sched/sch_sfq.c Sat Apr 24 17:51:48 1999
+++ linux/net/sched/sch_sfq.c Wed Jun 9 14:45:37 1999
@@ -387,7 +387,7 @@
X if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))


X return -EINVAL;
X
- start_bh_atomic();

+ sch_tree_lock(sch);
X q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
X q->perturb_period = ctl->perturb_period*HZ;
X
@@ -396,7 +396,7 @@
X q->perturb_timer.expires = jiffies + q->perturb_period;
X add_timer(&q->perturb_timer);
X }
- end_bh_atomic();
+ sch_tree_unlock(sch);
X return 0;
X }
X
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_tbf.c linux/net/sched/sch_tbf.c
--- v2.3.5/linux/net/sched/sch_tbf.c Sun Mar 21 07:22:00 1999
+++ linux/net/sched/sch_tbf.c Wed Jun 9 14:45:37 1999
@@ -308,7 +308,7 @@
X if (rtab->data[max_size>>qopt->rate.cell_log] > qopt->buffer)
X goto done;
X
- start_bh_atomic();
+ sch_tree_lock(sch);
X q->limit = qopt->limit;
X q->mtu = qopt->mtu;
X q->max_size = max_size;
@@ -317,7 +317,7 @@
X q->ptokens = q->mtu;
X rtab = xchg(&q->R_tab, rtab);
X ptab = xchg(&q->P_tab, ptab);
- end_bh_atomic();
+ sch_tree_unlock(sch);
X err = 0;
X done:
X if (rtab)
diff -u --recursive --new-file v2.3.5/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c
--- v2.3.5/linux/net/sched/sch_teql.c Sun Mar 21 07:22:00 1999
+++ linux/net/sched/sch_teql.c Wed Jun 9 14:45:37 1999
@@ -125,9 +125,11 @@


X if (skb == NULL) {

X struct device *m = dat->m->dev.qdisc->dev;
X if (m) {
- m->tbusy = 0;
X dat->m->slaves = sch;
+ spin_lock(&m->queue_lock);
+ m->tbusy = 0;
X qdisc_restart(m);
+ spin_unlock(&m->queue_lock);
X }
X }
X sch->q.qlen = dat->q.qlen + dat->m->dev.qdisc->q.qlen;
@@ -167,7 +169,9 @@
X master->slaves = NEXT_SLAVE(q);
X if (q == master->slaves) {
X master->slaves = NULL;
+ spin_lock_bh(&master->dev.queue_lock);
X qdisc_reset(master->dev.qdisc);
+ spin_unlock_bh(&master->dev.queue_lock);
X }
X }
X skb_queue_purge(&dat->q);
@@ -190,6 +194,9 @@
X if (dev->hard_header_len > m->dev.hard_header_len)
X return -EINVAL;
X
+ if (&m->dev == dev)
+ return -ELOOP;
+
X q->m = m;
X
X skb_queue_head_init(&q->q);
@@ -244,7 +251,11 @@
X return -ENOBUFS;
X }
X if (neigh_event_send(n, skb_res) == 0) {
- if (dev->hard_header(skb, dev, ntohs(skb->protocol), n->ha, NULL, skb->len) < 0) {
+ int err;
+ read_lock(&n->lock);
+ err = dev->hard_header(skb, dev, ntohs(skb->protocol), n->ha, NULL, skb->len);
+ read_unlock(&n->lock);
+ if (err < 0) {
X neigh_release(n);
X return -EINVAL;
X }
@@ -295,19 +306,24 @@
X continue;
X }
X
- if (q->h.forw == NULL) {


- q->h.forw = qdisc_head.forw;
- qdisc_head.forw = &q->h;
- }

+ if (!qdisc_on_runqueue(q))
+ qdisc_run(q);
X
X switch (teql_resolve(skb, skb_res, slave)) {
X case 0:
- if (slave->hard_start_xmit(skb, slave) == 0) {
- master->slaves = NEXT_SLAVE(q);


- dev->tbusy = 0;

- master->stats.tx_packets++;
- master->stats.tx_bytes += len;
+ if (spin_trylock(&slave->xmit_lock)) {
+ slave->xmit_lock_owner = smp_processor_id();
+ if (slave->hard_start_xmit(skb, slave) == 0) {
+ slave->xmit_lock_owner = -1;
+ spin_unlock(&slave->xmit_lock);
+ master->slaves = NEXT_SLAVE(q);


+ dev->tbusy = 0;

+ master->stats.tx_packets++;
+ master->stats.tx_bytes += len;
X return 0;
+ }
+ slave->xmit_lock_owner = -1;
+ spin_unlock(&slave->xmit_lock);
X }
X if (dev->tbusy)
X busy = 1;
diff -u --recursive --new-file v2.3.5/linux/net/socket.c linux/net/socket.c
--- v2.3.5/linux/net/socket.c Mon May 31 22:28:07 1999
+++ linux/net/socket.c Tue Jun 8 10:47:58 1999
@@ -204,7 +204,7 @@
X return -ENFILE;
X }
X
- file->f_dentry = d_alloc_root(inode, NULL);
+ file->f_dentry = d_alloc_root(inode);
X if (!file->f_dentry) {
X put_filp(file);
X put_unused_fd(fd);
diff -u --recursive --new-file v2.3.5/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.3.5/linux/net/sunrpc/xprt.c Tue May 4 10:29:07 1999
+++ linux/net/sunrpc/xprt.c Tue Jun 8 17:58:03 1999
@@ -42,6 +42,7 @@
X #define __KERNEL_SYSCALLS__
X
X #include <linux/version.h>
+#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/malloc.h>
X #include <linux/sched.h>
@@ -56,6 +57,8 @@
X #include <linux/file.h>
X
X #include <net/sock.h>
+#include <net/checksum.h>
+#include <net/udp.h>


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

@@ -356,6 +359,7 @@
X sk->user_data = NULL;
X #endif
X sk->data_ready = xprt->old_data_ready;
+ sk->no_check = 0;
X sk->state_change = xprt->old_state_change;
X sk->write_space = xprt->old_write_space;
X
@@ -563,18 +567,61 @@
X return;
X }
X
-/*
- * Input handler for RPC replies. Called from a bottom half and hence
+/* We have set things up such that we perform the checksum of the UDP
+ * packet in parallel with the copies into the RPC client iovec. -DaveM
+ */
+static int csum_partial_copy_to_page_cache(struct iovec *iov,
+ struct sk_buff *skb,
+ int copied)
+{
+ __u8 *pkt_data = skb->data + sizeof(struct udphdr);
+ __u8 *cur_ptr = iov->iov_base;
+ __kernel_size_t cur_len = iov->iov_len;
+ unsigned int csum = skb->csum;
+ int need_csum = (skb->ip_summed != CHECKSUM_UNNECESSARY);
+ int slack = skb->len - copied - sizeof(struct udphdr);
+
+ if (need_csum)
+ csum = csum_partial(skb->h.raw, sizeof(struct udphdr), csum);
+ while (copied > 0) {
+ if (cur_len) {
+ int to_move = cur_len;
+ if (to_move > copied)
+ to_move = copied;
+ if (need_csum)
+ csum = csum_partial_copy_nocheck(pkt_data, cur_ptr,
+ to_move, csum);
+ else
+ memcpy(cur_ptr, pkt_data, to_move);
+ pkt_data += to_move;
+ copied -= to_move;
+ cur_ptr += to_move;
+ cur_len -= to_move;
+ }
+ if (cur_len <= 0) {
+ iov++;
+ cur_len = iov->iov_len;
+ cur_ptr = iov->iov_base;
+ }
+ }
+ if (need_csum) {
+ if (slack > 0)
+ csum = csum_partial(pkt_data, slack, csum);
+ if ((unsigned short)csum_fold(csum))
+ return -1;
+ }


+ return 0;
+}
+

+/* Input handler for RPC replies. Called from a bottom half and hence
X * atomic.
X */
X static inline void
X udp_data_ready(struct sock *sk, int len)
X {
- struct rpc_task *task;
X struct rpc_xprt *xprt;
X struct rpc_rqst *rovr;
X struct sk_buff *skb;
- struct iovec iov[MAX_IOVEC];
X int err, repsize, copied;
X
X dprintk("RPC: udp_data_ready...\n");
@@ -584,28 +631,31 @@
X
X if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
X return;
- repsize = skb->len - 8; /* don't account for UDP header */
X
+ repsize = skb->len - sizeof(struct udphdr);
X if (repsize < 4) {
X printk("RPC: impossible RPC reply size %d!\n", repsize);
X goto dropit;
X }
X
X /* Look up the request corresponding to the given XID */
- if (!(rovr = xprt_lookup_rqst(xprt, *(u32 *) (skb->h.raw + 8))))
+ if (!(rovr = xprt_lookup_rqst(xprt,
+ *(u32 *) (skb->h.raw + sizeof(struct udphdr)))))
X goto dropit;
- task = rovr->rq_task;
X
- dprintk("RPC: %4d received reply\n", task->tk_pid);
- xprt_pktdump("packet data:", (u32 *) (skb->h.raw+8), repsize);
+ dprintk("RPC: %4d received reply\n", rovr->rq_task->tk_pid);
+ xprt_pktdump("packet data:",
+ (u32 *) (skb->h.raw + sizeof(struct udphdr)), repsize);
X
X if ((copied = rovr->rq_rlen) > repsize)
X copied = repsize;
X
- /* Okay, we have it. Copy datagram... */
- memcpy(iov, rovr->rq_rvec, rovr->rq_rnr * sizeof(iov[0]));
- /* This needs to stay tied with the usermode skb_copy_dagram... */
- memcpy_tokerneliovec(iov, skb->data+8, copied);
+ /* Suck it into the iovec, verify checksum if not done by hw. */
+ if (csum_partial_copy_to_page_cache(rovr->rq_rvec, skb, copied))
+ goto dropit;
+
+ /* Something worked... */
+ dst_confirm(skb->dst);
X
X xprt_complete_rqst(xprt, rovr, copied);
X
@@ -1341,6 +1391,7 @@
X xprt->old_write_space = inet->write_space;
X if (proto == IPPROTO_UDP) {
X inet->data_ready = udp_data_ready;
+ inet->no_check = UDP_CSUM_NORCV;
X } else {
X inet->data_ready = tcp_data_ready;
X inet->state_change = tcp_state_change;
diff -u --recursive --new-file v2.3.5/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c
--- v2.3.5/linux/net/wanrouter/wanmain.c Wed Dec 30 15:07:00 1998
+++ linux/net/wanrouter/wanmain.c Wed Jun 2 14:40:22 1999
@@ -30,6 +30,7 @@
X * Dec 22, 1998 Arnaldo Melo vmalloc/vfree used in device_setup to allocate
X * kernel memory and copy configuration data to
X * kernel space (for big firmwares)
+* May 19, 1999 Arnaldo Melo __initfunc in wanrouter_init
X *****************************************************************************/
X
X #include <linux/config.h>
@@ -104,17 +105,18 @@
X #endif
X
X #ifndef MODULE
-
-int wanrouter_init(void)
+__initfunc(int wanrouter_init(void))
X {
X int err;
- extern void wanpipe_init(void);
+ extern int wanpipe_init(void),
+ cyclomx_init(void);


X
X printk(KERN_INFO "%s v%u.%u %s\n",

X fullname, ROUTER_VERSION, ROUTER_RELEASE, copyright);
X err = wanrouter_proc_init();
X if (err)
- printk(KERN_ERR "%s: can't create entry in proc filesystem!\n", modname);
+ printk(KERN_ERR "%s: can't create entry in proc filesystem!\n",
+ modname);
X
X /*
X * Initialise compiled in boards
@@ -123,6 +125,9 @@
X #ifdef CONFIG_VENDOR_SANGOMA
X wanpipe_init();
X #endif
+#ifdef CONFIG_CYCLADES_SYNC
+ cyclomx_init();
+#endif


X return err;
X }
X

@@ -187,7 +192,6 @@
X * Context: process
X */
X
-
X int register_wan_device(wan_device_t* wandev)
X {
X int err, namelen;
@@ -207,7 +211,6 @@
X printk(KERN_INFO "%s: registering WAN device %s\n",
X modname, wandev->name);
X #endif
-
X /*
X * Register /proc directory entry
X */
diff -u --recursive --new-file v2.3.5/linux/net/x25/af_x25.c linux/net/x25/af_x25.c
--- v2.3.5/linux/net/x25/af_x25.c Wed Jun 2 14:44:39 1999
+++ linux/net/x25/af_x25.c Wed Jun 9 14:45:37 1999
@@ -1336,7 +1336,7 @@
X /*
X * Register any pre existing devices.


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

echo 'End of part 26'
echo 'File patch-2.3.6 is continued in part 27'
echo 27 > _shar_seq_.tmp

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

unread,
Jun 16, 1999, 3:00:00 AM6/16/99
to
Archive-name: v2.3/patch-2.3.6/part27

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


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

if test "$Scheck" != 27; then


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

X */


- read_lock_bh(&dev_base_lock);
+ read_lock(&dev_base_lock);
X 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)
@@ -1345,7 +1345,7 @@
X ))
X x25_link_device_up(dev);


X }
- read_unlock_bh(&dev_base_lock);
+ read_unlock(&dev_base_lock);
X

X return 0;
X }


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

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


echo 'restore of patch-2.3.6 failed'

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

0 new messages